Я пытаюсь сделать решатель 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
и updateObject1 objs0 obj0 = ... returnA -< obj
должны привести к обновлению всех объектов, а следующий итерационный цикл должен передать gravity1 :: ([Object], Object) -> SF () (Object)
обновленный набор объектов, так что значение acc
будет другим в каждом кадре. ..
Я неправильно понимаю логику того, как здесь все должно работать?