 
 (defn calculate-ground-forces [nodes]
     (zipmap (keys nodes)
-        (map (fn [{[ x y ] :pos [ xv yv ] :vel }]
+        (map (fn [{[ _ y ] :pos}]
             (if (< y 0)
-                (vec+
-                    (vec* [(- xv) (Math/max 0 (- yv))] ground-grip-strength)
-                    (vec* [0 (- y)] ground-rebound-strength))
-                [0 0])) (vals nodes))))
-
-(defn calculate-drag-forces [nodes]
-    (zipmap (keys nodes)
-        (map (fn [{v :vel m :mass}] (vec* v (- (* m drag-factor))))
+                (vec* [0 (- y)] ground-rebound-strength)
+                [0 0]))
             (vals nodes))))
+
+(defn calculate-ground-impulses [nodes time-step]
+    (let [loss (- 1.0 (Math/exp (- (* time-step ground-drag-factor))))]
+        (zipmap (keys nodes)
+            (map (fn [{[ _ y ] :pos [ xv yv ] :vel mass :mass}]
+                (if (< y 0)
+                    (vec* [(- xv) (Math/max 0 (- yv))] (* loss mass))
+                    [0 0]))
+                (vals nodes)))))
+
+(defn calculate-air-impulses [nodes time-step]
+    (let [loss (- 1.0 (Math/exp (- (* time-step air-drag-factor))))]
+        (zipmap (keys nodes)
+            (map (fn [{[_ y] :pos vel :vel mass :mass}]
+                (if (< y 0)
+                    [0 0]
+                    (vec* vel (* -1 loss mass))))
+                (vals nodes)))))
 
 (defn calculate-all-node-forces [{:keys [nodes springs hinges]}]
     (merge-with vec+
         (calculate-spring-forces nodes springs)
         (calculate-hinge-forces nodes hinges)
         (calculate-gravity-forces nodes)
-        (calculate-ground-forces nodes)
-        (calculate-drag-forces nodes)))
-
-(defn update-node-velocities [nodes forces time-step]
-    (merge-with (fn [n f]
-        (assoc n
-            :vel (vec+ (:vel n) (vec* f (/ time-step (:mass n))))))
-        nodes
-        forces))
+        (calculate-ground-forces nodes)))
+
+(defn calculate-all-node-impulses [nodes time-step]
+    (merge-with vec+
+        (calculate-ground-impulses nodes time-step)
+        (calculate-air-impulses nodes time-step)))
+
+(defn update-node-velocities [nodes forces impulses time-step]
+    (merge-with
+        (fn [n i] (assoc n
+            :vel (vec+
+                (:vel n)
+                (vec* i (/ 1.0 (:mass n))))))
+        (merge-with
+            (fn [n f] (assoc n
+                :vel (vec+
+                    (:vel n)
+                    (vec* f (/ time-step (:mass n))))))
+            nodes
+            forces)
+        impulses))
 
 (defn update-node-positions [nodes time-step]
     (zipmap (keys nodes) (map (fn [n]

                c (vec- (:pos (nodes (:node-c h))) (:pos (nodes (:node-b h))))]
                (angle a c))
            :modifier-angle 0.0
            :strength 1000000))
        hinges)
})



(defn hinge-nodes [h]
    (map h [:node-a :node-b :node-c]))

(defn now-in-milliseconds []
    (. (goog.date.UtcDateTime.) (getTime)))

(defn delta [f]
    (let [prev (atom (f))] (fn []
        (let [next (f) result (- next @prev)] (do
            (reset! prev next)
            result)))))

(defn limiter [f]
    (fn [] (Math/min (* 1000 worst-tick-step) (f))))

(defn smooth [f]
    (let [prev (atom 0.0)] (fn []
        (let [next (f) result (+ (* 0.01 next) (* 0.99 @prev))] (do
            (reset! prev result)
            result)))))

(def real-tick-step
    (smooth (limiter (delta now-in-milliseconds))))

(defn tick-imp [state tick-step input-state]
    (assoc state
