diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp
index 60a9b22a3..236e9c5df 100644
--- a/apps/openmw/mwrender/renderingmanager.cpp
+++ b/apps/openmw/mwrender/renderingmanager.cpp
@@ -322,10 +322,9 @@ void RenderingManager::update (float duration, bool paused)
 
         btVector3 btOrig(orig.x, orig.y, orig.z);
         btVector3 btDest(dest.x, dest.y, dest.z);
-        std::pair<std::string,float> test = mPhysicsEngine->rayTest(btOrig, btDest);
-        if (!test.first.empty()) {
+        std::pair<bool, float> test = mPhysicsEngine->sphereCast(mRendering.getCamera()->getNearClipDistance()*2.5, btOrig, btDest);
+        if (test.first)
             mCamera->setCameraDistance(test.second * orig.distance(dest), false, false);
-        }
     }
 
     mOcclusionQuery->update(duration);
diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp
index ce32b79e5..086950574 100644
--- a/apps/openmw/mwworld/physicssystem.cpp
+++ b/apps/openmw/mwworld/physicssystem.cpp
@@ -33,23 +33,23 @@ namespace MWWorld
     class MovementSolver
     {
     private:
-        static bool stepMove(Ogre::Vector3& position, const Ogre::Vector3 &velocity, float remainingTime,
+        static bool stepMove(Ogre::Vector3& position, const Ogre::Quaternion& orient, const Ogre::Vector3 &velocity, float remainingTime,
                              const Ogre::Vector3 &halfExtents, bool isInterior,
                              OEngine::Physic::PhysicEngine *engine)
         {
             traceResults trace; // no initialization needed
 
-            newtrace(&trace, position, position+Ogre::Vector3(0.0f,0.0f,sStepSize),
+            newtrace(&trace, orient, position, position+Ogre::Vector3(0.0f,0.0f,sStepSize),
                      halfExtents, isInterior, engine);
             if(trace.fraction == 0.0f)
                 return false;
 
-            newtrace(&trace, trace.endpos, trace.endpos + velocity*remainingTime,
+            newtrace(&trace, orient, trace.endpos, trace.endpos + velocity*remainingTime,
                      halfExtents, isInterior, engine);
             if(trace.fraction == 0.0f || (trace.fraction != 1.0f && getSlope(trace.planenormal) > sMaxSlope))
                 return false;
 
-            newtrace(&trace, trace.endpos, trace.endpos-Ogre::Vector3(0.0f,0.0f,sStepSize), halfExtents, isInterior, engine);
+            newtrace(&trace, orient, trace.endpos, trace.endpos-Ogre::Vector3(0.0f,0.0f,sStepSize), halfExtents, isInterior, engine);
             if(getSlope(trace.planenormal) <= sMaxSlope)
             {
                 // only step down onto semi-horizontal surfaces. don't step down onto the side of a house or a wall.
@@ -105,24 +105,19 @@ namespace MWWorld
             physicActor->enableCollisions(false);
 
             Ogre::Vector3 halfExtents = physicActor->getHalfExtents();// + Vector3(1,1,1);
+            halfExtents.z = 1; // we trace the feet only, so we use a very thin box
 
             Ogre::Vector3 newPosition = position;
 
             traceResults trace; //no initialization needed
 
-            int maxHeight = 400.f;
-            int steps = 100;
-            for (int i=0; i<steps; ++i)
-            {
-                newtrace(&trace, newPosition, newPosition-Ogre::Vector3(0,0,maxHeight / steps), halfExtents, isInterior, engine);
-                if(trace.fraction < 1.0f)
-                    hit = true;
-                newPosition = trace.endpos;
-            }
-
+            int maxHeight = 200.f;
+            newtrace(&trace, Ogre::Quaternion::IDENTITY, newPosition, newPosition-Ogre::Vector3(0,0,maxHeight), halfExtents, isInterior, engine);
+            if(trace.fraction < 1.0f)
+                hit = true;
             newPosition = trace.endpos;
 
-            physicActor->setOnGround(hit);
+            physicActor->setOnGround(hit && getSlope(trace.planenormal) <= sMaxSlope);
             physicActor->enableCollisions(wasCollisionMode);
 
             if (hit)
@@ -154,7 +149,7 @@ namespace MWWorld
             bool isInterior = !ptr.getCell()->isExterior();
             Ogre::Vector3 halfExtents = physicActor->getHalfExtents();// + Vector3(1,1,1);
             physicActor->enableCollisions(false);
-
+            Ogre::Quaternion orient = Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::UNIT_Z);
             Ogre::Vector3 velocity;
             if(!gravity)
             {
@@ -167,7 +162,7 @@ namespace MWWorld
             {
                 if(!(movement.z > 0.0f))
                 {
-                    newtrace(&trace, position, position-Ogre::Vector3(0,0,4), halfExtents, isInterior, engine);
+                    newtrace(&trace, orient, position, position-Ogre::Vector3(0,0,4), halfExtents, isInterior, engine);
                     if(trace.fraction < 1.0f && getSlope(trace.planenormal) <= sMaxSlope)
                         onground = true;
                 }
@@ -188,7 +183,7 @@ namespace MWWorld
             int iterations = 0;
             do {
                 // trace to where character would go if there were no obstructions
-                newtrace(&trace, newPosition, newPosition+clippedVelocity*remainingTime, halfExtents, isInterior, engine);
+                newtrace(&trace, orient, newPosition, newPosition+clippedVelocity*remainingTime, halfExtents, isInterior, engine);
                 newPosition = trace.endpos;
                 remainingTime = remainingTime * (1.0f-trace.fraction);
 
@@ -207,7 +202,7 @@ namespace MWWorld
                     {
                         // Can't walk on this. Try to step up onto it.
                         if((gravity && !onground) ||
-                           !stepMove(newPosition, velocity, remainingTime, halfExtents, isInterior, engine))
+                           !stepMove(newPosition, orient, velocity, remainingTime, halfExtents, isInterior, engine))
                         {
                             Ogre::Vector3 resultantDirection = trace.planenormal.crossProduct(up);
                             resultantDirection.normalise();
@@ -225,7 +220,7 @@ namespace MWWorld
 
             if(onground)
             {
-                newtrace(&trace, newPosition, newPosition-Ogre::Vector3(0,0,sStepSize+4.0f), halfExtents, isInterior, engine);
+                newtrace(&trace, orient, newPosition, newPosition-Ogre::Vector3(0,0,sStepSize+4.0f), halfExtents, isInterior, engine);
                 if(trace.fraction < 1.0f && getSlope(trace.planenormal) <= sMaxSlope)
                     newPosition.z = trace.endpos.z + 2.0f;
                 else
diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp
index a903369ee..9a08a1635 100644
--- a/apps/openmw/mwworld/worldimp.cpp
+++ b/apps/openmw/mwworld/worldimp.cpp
@@ -911,7 +911,7 @@ namespace MWWorld
         float terrainHeight = mRendering->getTerrainHeightAt(pos);
 
         if (pos.z < terrainHeight)
-            pos.z = terrainHeight+400; // place slightly above. will snap down to ground with code below
+            pos.z = terrainHeight+5; // place slightly above. will snap down to ground with code below
 
         ptr.getRefData().getPosition().pos[2] = pos.z;
 
@@ -973,6 +973,8 @@ namespace MWWorld
         if(duration <= 0.0f)
             return;
 
+        processDoors(duration);
+
         PtrMovementList::const_iterator player(actors.end());
         for(PtrMovementList::const_iterator iter(actors.begin());iter != actors.end();iter++)
         {
@@ -998,8 +1000,6 @@ namespace MWWorld
             moveObjectImp(player->first, vec.x, vec.y, vec.z);
         }
 
-        processDoors(duration);
-
         mPhysEngine->stepSimulation (duration);
     }
 
@@ -1022,6 +1022,7 @@ namespace MWWorld
                 mPhysics->getObjectAABB(it->first, min, max);
                 Ogre::Vector3 dimensions = max-min;
 
+                /// \todo should use convexSweepTest here
                 std::vector<std::string> collisions = mPhysics->getCollisions(it->first);
                 for (std::vector<std::string>::iterator cit = collisions.begin(); cit != collisions.end(); ++cit)
                 {
diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp
index dbb42a645..def69a2e8 100644
--- a/libs/openengine/bullet/physic.cpp
+++ b/libs/openengine/bullet/physic.cpp
@@ -622,6 +622,41 @@ namespace Physic
         return std::pair<std::string,float>(name,d);
     }
 
+    // callback that ignores player in results
+    struct	OurClosestConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
+    {
+    public:
+        OurClosestConvexResultCallback(const btVector3&	convexFromWorld,const btVector3&	convexToWorld)
+            : btCollisionWorld::ClosestConvexResultCallback(convexFromWorld, convexToWorld) {}
+
+        virtual	btScalar	addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
+        {
+            if (const RigidBody* body = dynamic_cast<const RigidBody*>(convexResult.m_hitCollisionObject))
+                if (body->mName == "player")
+                    return 0;
+            return btCollisionWorld::ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
+        }
+    };
+
+    std::pair<bool, float> PhysicEngine::sphereCast (float radius, btVector3& from, btVector3& to)
+    {
+        OurClosestConvexResultCallback callback(from, to);
+        callback.m_collisionFilterMask = OEngine::Physic::CollisionType_World;
+
+        btSphereShape shape(radius);
+        const btQuaternion btrot(0.0f, 0.0f, 0.0f);
+
+        btTransform from_ (btrot, from);
+        btTransform to_ (btrot, to);
+
+        dynamicsWorld->convexSweepTest(&shape, from_, to_, callback);
+
+        if (callback.hasHit())
+            return std::make_pair(true, callback.m_closestHitFraction);
+        else
+            return std::make_pair(false, 1);
+    }
+
     std::vector< std::pair<float, std::string> > PhysicEngine::rayTest2(btVector3& from, btVector3& to)
     {
         MyRayResultCallback resultCallback1;
diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp
index 6d88fcb55..8b246408a 100644
--- a/libs/openengine/bullet/physic.hpp
+++ b/libs/openengine/bullet/physic.hpp
@@ -298,6 +298,9 @@ namespace Physic
          */
         std::vector< std::pair<float, std::string> > rayTest2(btVector3& from, btVector3& to);
 
+        std::pair<bool, float> sphereCast (float radius, btVector3& from, btVector3& to);
+        ///< @return (hit, relative distance)
+
         std::vector<std::string> getCollisions(const std::string& name);
 
         //event list of non player object
diff --git a/libs/openengine/bullet/trace.cpp b/libs/openengine/bullet/trace.cpp
index cc443f267..6ed2a9291 100644
--- a/libs/openengine/bullet/trace.cpp
+++ b/libs/openengine/bullet/trace.cpp
@@ -15,16 +15,16 @@ enum traceWorldType
     bothWorldTrace = collisionWorldTrace | pickWorldTrace
 };
 
-void newtrace(traceResults *results, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, bool isInterior, OEngine::Physic::PhysicEngine *enginePass)  //Traceobj was a Aedra Object
+void newtrace(traceResults *results, const Ogre::Quaternion& orient, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, bool isInterior, OEngine::Physic::PhysicEngine *enginePass)  //Traceobj was a Aedra Object
 {
     const btVector3 btstart(start.x, start.y, start.z + BBHalfExtents.z);
     const btVector3 btend(end.x, end.y, end.z + BBHalfExtents.z);
-    const btQuaternion btrot(0.0f, 0.0f, 0.0f);   //y, x, z
+    const btQuaternion btorient (orient.x, orient.y, orient.z, orient.w);
 
     const btBoxShape newshape(btVector3(BBHalfExtents.x, BBHalfExtents.y, BBHalfExtents.z));
     //const btCapsuleShapeZ newshape(BBHalfExtents.x, BBHalfExtents.z * 2 - BBHalfExtents.x * 2);
-    const btTransform from(btrot, btstart);
-    const btTransform to(btrot, btend);
+    const btTransform from(btorient, btstart);
+    const btTransform to(btorient, btend);
 
     btCollisionWorld::ClosestConvexResultCallback newTraceCallback(btstart, btend);
     newTraceCallback.m_collisionFilterMask = OEngine::Physic::CollisionType_World;
diff --git a/libs/openengine/bullet/trace.h b/libs/openengine/bullet/trace.h
index f484497d9..cd2547f8c 100644
--- a/libs/openengine/bullet/trace.h
+++ b/libs/openengine/bullet/trace.h
@@ -21,6 +21,6 @@ struct traceResults
     float fraction;
 };
 
-void newtrace(traceResults *results, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, bool isInterior, OEngine::Physic::PhysicEngine* enginePass);
+void newtrace(traceResults *results, const Ogre::Quaternion& orient, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, bool isInterior, OEngine::Physic::PhysicEngine* enginePass);
 
 #endif