diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp
index 7df8d8191..2dfeb6afe 100644
--- a/src/tracks/track.cpp
+++ b/src/tracks/track.cpp
@@ -142,7 +142,7 @@ Track::Track(const std::string &filename)
     m_startup_run = false;
     m_default_number_of_laps= 3;
     m_all_nodes.clear();
-    m_all_physics_only_nodes.clear();
+    m_static_physics_only_nodes.clear();
     m_all_cached_meshes.clear();
     loadTrackInfo();
 }   // Track
@@ -293,7 +293,7 @@ void Track::cleanup()
         irr_driver->removeNode(m_all_nodes[i]);
     }
     m_all_nodes.clear();
-    m_all_physics_only_nodes.clear();
+    m_static_physics_only_nodes.clear();
 
     m_all_emitters.clearAndDeleteAll();
 
@@ -302,6 +302,12 @@ void Track::cleanup()
     delete m_track_object_manager;
     m_track_object_manager = NULL;
 
+    for (unsigned int i = 0; i < m_object_physics_only_nodes.size(); i++)
+    {
+        m_object_physics_only_nodes[i]->drop();
+    }
+    m_object_physics_only_nodes.clear();
+
     irr_driver->removeNode(m_sun);
 
     delete m_track_mesh;
@@ -720,6 +726,24 @@ void Track::createPhysicsModel(unsigned int main_track_count)
         return;
     }
 
+
+    // Now convert all objects that are only used for the physics
+    // (like invisible walls).
+    for (unsigned int i = 0; i<m_static_physics_only_nodes.size(); i++)
+    {
+        convertTrackToBullet(m_static_physics_only_nodes[i]);
+        irr_driver->removeNode(m_static_physics_only_nodes[i]);
+    }
+    m_static_physics_only_nodes.clear();
+
+    for (unsigned int i = 0; i<m_object_physics_only_nodes.size(); i++)
+    {
+        convertTrackToBullet(m_object_physics_only_nodes[i]);
+        m_object_physics_only_nodes[i]->setVisible(false);
+        m_object_physics_only_nodes[i]->grab();
+        irr_driver->removeNode(m_object_physics_only_nodes[i]);
+    }
+
     m_track_mesh->removeAll();
     m_gfx_effect_mesh->removeAll();
     for(unsigned int i=main_track_count; i<m_all_nodes.size(); i++)
@@ -1377,7 +1401,7 @@ bool Track::loadMainTrack(const XMLNode &root)
             else
             {
                 if(interaction=="physics-only")
-                    m_all_physics_only_nodes.push_back( scene_node );
+                    m_static_physics_only_nodes.push_back(scene_node);
                 else
                     m_all_nodes.push_back( scene_node );
             }
@@ -1391,15 +1415,6 @@ bool Track::loadMainTrack(const XMLNode &root)
         convertTrackToBullet(m_all_nodes[i]);
     }
 
-    // Now convert all objects that are only used for the physics
-    // (like invisible walls).
-    for(unsigned int i=0; i<m_all_physics_only_nodes.size(); i++)
-    {
-        convertTrackToBullet(m_all_physics_only_nodes[i]);
-        irr_driver->removeNode(m_all_physics_only_nodes[i]);
-    }
-    m_all_physics_only_nodes.clear();
-
     if (m_track_mesh == NULL)
     {
         Log::fatal("track", "m_track_mesh == NULL, cannot loadMainTrack\n");
diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp
index 635d913f6..e4da819de 100644
--- a/src/tracks/track.hpp
+++ b/src/tracks/track.hpp
@@ -184,7 +184,12 @@ private:
 
     /** The list of all nodes that are to be converted into physics,
      *  but not to be drawn (e.g. invisible walls). */
-    std::vector<scene::ISceneNode*> m_all_physics_only_nodes;
+    std::vector<scene::ISceneNode*> m_static_physics_only_nodes;
+
+    /** Same concept but for track objects. stored separately due to different
+      * memory management.
+      */
+    std::vector<scene::ISceneNode*> m_object_physics_only_nodes;
 
     /** The list of all meshes that are loaded from disk, which means
      *  that those meshes are being cached by irrlicht, and need to be freed. */
@@ -651,6 +656,11 @@ public:
     // ------------------------------------------------------------------------
     void addNode(scene::ISceneNode* node) { m_all_nodes.push_back(node); }
     // ------------------------------------------------------------------------
+    void addPhysicsOnlyNode(scene::ISceneNode* node)
+    {
+        m_object_physics_only_nodes.push_back(node);
+    }
+    // ------------------------------------------------------------------------
     float getDisplacementSpeed() const { return m_displacement_speed;    }
     // ------------------------------------------------------------------------
     float getCausticsSpeed() const { return m_caustics_speed;        }
diff --git a/src/tracks/track_object_manager.cpp b/src/tracks/track_object_manager.cpp
index 8545ebc32..e2f940ffd 100644
--- a/src/tracks/track_object_manager.cpp
+++ b/src/tracks/track_object_manager.cpp
@@ -42,13 +42,6 @@ TrackObjectManager::~TrackObjectManager()
 // ----------------------------------------------------------------------------
 /** Adds an object to the track object manager. The type to add is specified
  *  in the xml_node.
- * \note If you add add any objects with LOD, don't forget to call
- *       TrackObjectManager::assingLodNodes after everything is loaded
- *       to finalize their creation.
- *
- * FIXME: all of this is horrible, just make the exporter write LOD definitions
- *        in a separate section that's read before everything and remove all this
- *        crap
  */
 void TrackObjectManager::add(const XMLNode &xml_node, scene::ISceneNode* parent,
                              ModelDefinitionLoader& model_def_loader)
@@ -351,21 +344,4 @@ void TrackObjectManager::removeObject(TrackObject* obj)
 
 // ----------------------------------------------------------------------------
 
-/*
-void TrackObjectManager::assingLodNodes(const std::vector<LODNode*>& lod_nodes)
-{
-    for (unsigned int n=0; n<lod_nodes.size(); n++)
-    {
-        std::vector<const XMLNode*>& queue = m_lod_objects[ lod_nodes[n]->getGroupName() ];
-        assert( queue.size() > 0 );
-        const XMLNode* xml = queue[ queue.size() - 1 ];
 
-        TrackObject* obj = new TrackObject(*xml, lod_nodes[n]->getParent(), lod_nodes[n]);
-        queue.erase( queue.end() - 1 );
-
-        m_all_objects.push_back(obj);
-    }
-
-    m_lod_objects.clear();
-}
-*/
diff --git a/src/tracks/track_object_presentation.cpp b/src/tracks/track_object_presentation.cpp
index 55a20c61e..e6557c100 100644
--- a/src/tracks/track_object_presentation.cpp
+++ b/src/tracks/track_object_presentation.cpp
@@ -384,14 +384,28 @@ void TrackObjectPresentationMesh::init(const XMLNode* xml_node,
     bool animated = skeletal_animation && (UserConfigParams::m_graphical_effects ||
              World::getWorld()->getIdent() == IDENT_CUTSCENE);
     bool displacing = false;
-    if(xml_node)
+    std::string interaction;
+    if (xml_node)
+    {
         xml_node->get("displacing", &displacing);
+        xml_node->get("interaction", &interaction);
+    }
     animated &= !displacing;
 
     m_mesh->grab();
     irr_driver->grabAllTextures(m_mesh);
 
-    if (m_is_in_skybox)
+    if (interaction == "physicsonly")
+    {
+        m_node = irr_driver->addMesh(m_mesh, m_model_file, parent);
+        enabled = false;
+        m_frame_start = 0;
+        m_frame_end = 0;
+
+        if (World::getWorld() && World::getWorld()->getTrack() && xml_node)
+            World::getWorld()->getTrack()->addPhysicsOnlyNode(m_node);
+    }
+    else if (m_is_in_skybox)
     {
         // Tell the driver that this mesh is a part of the background
         scene::IMeshSceneNode * const node =