我正在尝试制作一个 n 体求解器(一堆相互引力吸引的物体)。问题是它看起来像gravity1函数没有反馈返回的对象,导致对象的线性运动:
代码如下所示:
updateGame :: Game -> SF AppInput Game
updateGame game =
proc input -> do
...
objs <- updateObjects' $ _foreground (Game._objects game) -< ()
...
updateObjects' :: [Object] -> SF () [Object]
updateObjects' objs = parB . fmap (updateObject1 objs ) $ objs
updateObject1 :: [Object] -> Object -> SF () Object
updateObject1 objs0 obj0 =
proc () -> do
obj <- gravity1 (objs0, obj0) -< ()
returnA -< obj
g = 6.673**(-11.0) :: Double
gravity1 :: ([Object], Object) -> SF () (Object)
gravity1 (objs0, obj0) =
proc () -> do
let
m0 = _mass obj0 :: Double
xform0 = (head . _transforms) obj0 :: M44 Double
p0 = ( view (_w._xyz)) xform0 :: V3 Double
ms = foldr1 (+) $ fmap (_mass) objs0 :: Double
xforms = fmap (head . _transforms) objs0 :: [M44 Double]
ps = foldr1 (^+^) $ fmap ( view (_w._xyz)) xforms :: V3 Double
dir = ps ^-^ p0 :: V3 Double
dist = norm dir :: Double
f = g * m0 * ms / dist**2.0 :: Double
acc = (f / ms) *^ (dir ^/ dist) :: V3 Double
s = 1000000000000000.0
--vel <- ((_velocity obj0) ^+^) ^<< integral -< (s *^ acc)
vel <- ((_velocity obj0) ^+^) ^<< integral -< (s *^ (DT.trace ("acc :" ++ show (s *^ acc)) $ acc))
let mtx =
mkTransformationMat
rot
tr
where
rot = (view _m33 xform0)
tr = vel + p0
returnA -< obj0 { _transforms = [mtx]
, _velocity = vel }
运行代码,有我在控制台中读取的输出:
acc :V3 12105.49700148636 12105.49700148636 0.0
acc :V3 NaN NaN NaN
acc :V3 (-12105.49700148636) 12105.49700148636 0.0
acc :V3 12105.49700148636 12105.49700148636 0.0
acc :V3 NaN NaN NaN
acc :V3 (-12105.49700148636) 12105.49700148636 0.0
acc :V3 12105.49700148636 12105.49700148636 0.0
acc :V3 NaN NaN NaN
acc :V3 (-12105.49700148636) 12105.49700148636 0.0
acc :V3 12105.49700148636 12105.49700148636 0.0
acc :V3 NaN NaN NaN
acc :V3 (-12105.49700148636) 12105.49700148636 0.0
acc :V3 12105.49700148636 12105.49700148636 0.0
acc :V3 NaN NaN NaN
acc :V3 (-12105.49700148636) 12105.49700148636 0.0
acc :V3 12105.49700148636 12105.49700148636 0.0
acc :V3 NaN NaN NaN
acc :V3 (-12105.49700148636) 12105.49700148636 0.0
acc :V3 12105.49700148636 12105.49700148636 0.0
acc :V3 NaN NaN NaN
基本上这些值都是相同的(NaN 是由于对自身计算的对象,我应该解决这个问题,但这不是这里的问题),看起来gravity1 函数没有反馈返回对象,尽管返回值是:
returnA -< obj0 { _transforms = [mtx]
, _velocity = vel }
结果是对象的线性运动,因为 acc 似乎是一个常数。
我在这里的期望是,在gravity1 :: ([Object], Object) -> SF () (Object)
更新并返回对象之后,updateObjects' objs = parB . fmap (updateObject1 objs ) $ objs
andupdateObject1 objs0 obj0 = ... returnA -< obj
应该导致所有对象都被更新,并且下一个迭代周期应该gravity1 :: ([Object], Object) -> SF () (Object)
为对象提供一组更新的对象,以便acc
每一帧的值都不同......
我是否误解了这里应该如何运作的逻辑?