From 47832170e1b107b6a937e9d46bf07d7502abe159 Mon Sep 17 00:00:00 2001
From: Marc Sunet <jeannekamikaze@gmail.com>
Date: Fri, 31 Aug 2012 22:26:56 +0200
Subject: Added ability to choose how 2d rotations should be mapped to 3d

---
 Spear.lkshs               | 10 ++++----
 Spear.lkshw               |  2 +-
 Spear/Math/MatrixUtils.hs | 59 +++++++++++++++++++++++++----------------------
 Spear/Scene/GameObject.hs | 53 +++++++++++++++++++++++++++++++++---------
 Spear/Scene/Loader.hs     | 18 +++++++++++----
 5 files changed, 92 insertions(+), 50 deletions(-)

diff --git a/Spear.lkshs b/Spear.lkshs
index 5ee07cf..4b0d469 100644
--- a/Spear.lkshs
+++ b/Spear.lkshs
@@ -1,18 +1,18 @@
 Version of session file format:
                1
 Time of storage:
-               "Fri Aug 31 16:57:11 CEST 2012"
-Layout:        VerticalP (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = 4, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [("Browser",HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 290) 209),("Debug",HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = 1, detachedId = Nothing, detachedSize = Nothing}) 246)], paneTabs = Just BottomP, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 639) 954
-Population:    [(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/Program/Box.hs" 1712)),[SplitP LeftP]),(Just (BreakpointsSt BreakpointsState),[SplitP RightP,SplitP TopP,GroupP "Debug",SplitP BottomP]),(Just (ErrorsSt ErrorsState),[SplitP RightP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Factory.hs" 1309)),[SplitP LeftP]),(Just (FilesSt FilesState),[SplitP RightP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/GLSL.hs" 13235)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Scene/GameObject.hs" 4522)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject.hs" 1652)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameState.hs" 584)),[SplitP LeftP]),(Just (InfoSt (InfoState Nothing)),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP BottomP]),(Just (LogSt LogState),[SplitP RightP,SplitP BottomP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model.hsc" 15715)),[SplitP LeftP]),(Just (ModulesSt (ModulesState 328 (PackageScope False,False) (Just (ModuleName ["Game","GameState"]),Nothing) (ExpanderState {packageExp = ([],[]), packageExpNoBlack = ([[0]],[]), packageDExp = ([],[]), packageDExpNoBlack = ([],[]), workspaceExp = ([],[]), workspaceExpNoBlack = ([],[]), workspaceDExp = ([],[]), workspaceDExpNoBlack = ([],[]), systemExp = ([],[]), systemExpNoBlack = ([],[])}))),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP TopP]),(Just (SearchSt (SearchState {searchString = "putStrLn", searchScope = PackageScope False, searchMode = Prefix {caseSense = False}})),[SplitP RightP,SplitP TopP]),(Just (TraceSt TraceState),[SplitP RightP,SplitP TopP,GroupP "Debug",SplitP BottomP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Utils.hs" 726)),[SplitP LeftP]),(Just (VariablesSt VariablesState),[SplitP RightP,SplitP TopP,GroupP "Debug",SplitP BottomP]),(Just (WorkspaceSt WorkspaceState),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP TopP]),(Just (BufferSt (BufferStateTrans "_Eval.hs" "\n" 0)),[SplitP RightP,SplitP TopP,GroupP "Debug",SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/demos/simple-scene/main.hs" 2287)),[SplitP LeftP])]
+               "Fri Aug 31 22:25:44 CEST 2012"
+Layout:        VerticalP (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = 1, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [("Browser",HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 302) 217),("Debug",HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = 1, detachedId = Nothing, detachedSize = Nothing}) 256)], paneTabs = Just BottomP, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 663) 954
+Population:    [(Just (BreakpointsSt BreakpointsState),[SplitP RightP,SplitP TopP,GroupP "Debug",SplitP BottomP]),(Just (ErrorsSt ErrorsState),[SplitP RightP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Factory.hs" 1205)),[SplitP LeftP]),(Just (FilesSt FilesState),[SplitP RightP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Scene/GameObject.hs" 3114)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject.hs" 1432)),[SplitP LeftP]),(Just (InfoSt (InfoState Nothing)),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP BottomP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Scene/Loader.hs" 17178)),[SplitP LeftP]),(Just (LogSt LogState),[SplitP RightP,SplitP BottomP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Math/MatrixUtils.hs" 1235)),[SplitP LeftP]),(Just (ModulesSt (ModulesState 328 (PackageScope False,False) (Nothing,Nothing) (ExpanderState {packageExp = ([],[]), packageExpNoBlack = ([[0]],[]), packageDExp = ([],[]), packageDExpNoBlack = ([],[]), workspaceExp = ([],[]), workspaceExpNoBlack = ([],[]), workspaceDExp = ([],[]), workspaceDExpNoBlack = ([],[]), systemExp = ([],[]), systemExpNoBlack = ([],[])}))),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Player.hs" 2249)),[SplitP LeftP]),(Just (SearchSt (SearchState {searchString = "putStrLn", searchScope = PackageScope False, searchMode = Prefix {caseSense = False}})),[SplitP RightP,SplitP TopP]),(Just (TraceSt TraceState),[SplitP RightP,SplitP TopP,GroupP "Debug",SplitP BottomP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Utils.hs" 587)),[SplitP LeftP]),(Just (VariablesSt VariablesState),[SplitP RightP,SplitP TopP,GroupP "Debug",SplitP BottomP]),(Just (WorkspaceSt WorkspaceState),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP TopP]),(Just (BufferSt (BufferStateTrans "_Eval.hs" "\n" 0)),[SplitP RightP,SplitP TopP,GroupP "Debug",SplitP TopP])]
 Window size:   (1820,944)
 Completion size:
                (750,399)
 Workspace:     Just "/home/jeanne/programming/haskell/Spear/Spear.lkshw"
-Active pane:   Just "GameObject.hs(1)"
+Active pane:   Just "GameObject.hs"
 Toolbar visible:
                True
 FindbarState:  (False,FindState {entryStr = "986", entryHist = ["986","drawElements","56","drawArray","drawVA","f","SV","VAO","'VAO'","\170","\\","^"], replaceStr = "V3.", replaceHist = [], caseSensitive = True, entireWord = False, wrapAround = False, regex = False, lineNr = 1})
 Recently opened files:
-               ["/home/jeanne/programming/haskell/Spear/demos/simple-scene/main.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/Program/Box.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameState.hs","/home/jeanne/programming/haskell/Spear/Spear/Setup.hs","/home/jeanne/programming/haskell/Spear/Spear/Scene/SceneResources.hs","/home/jeanne/programming/haskell/Spear/Spear/Scene/Loader.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Utils.hs","/home/jeanne/programming/haskell/Spear/Spear/Render/Texture.hs","/home/jeanne/programming/haskell/Spear/Spear/Render/AnimatedModel.hs","/home/jeanne/programming/haskell/Spear/Spear/Render/StaticModel.hs","/home/jeanne/programming/haskell/Spear/Spear/Render/Program.hs"]
+               ["/home/jeanne/programming/haskell/Spear/Spear/Math/Spatial2.hs","/home/jeanne/programming/haskell/Spear/Spear/Math/Matrix4.hs","/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/Model.c","/home/jeanne/programming/haskell/Spear/Spear/Assets/Model.hsc","/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/Model.h","/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/OBJ/OBJ_load.c","/home/jeanne/programming/haskell/Spear/demos/simple-scene/main.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/Program/Box.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameState.hs","/home/jeanne/programming/haskell/Spear/Spear/Setup.hs","/home/jeanne/programming/haskell/Spear/Spear/Scene/SceneResources.hs","/home/jeanne/programming/haskell/Spear/Spear/Scene/Loader.hs"]
 Recently opened workspaces:
                ["/home/jeanne/programming/haskell/hagen/hagen.lkshw","/home/jeanne/programming/haskell/foo/foo.lkshw","/home/jeanne/programming/haskell/Spear/Spear.lkshw","/home/jeanne/programming/haskell/nexus/nexus.lkshw","/home/jeanne/leksah.lkshw"]
\ No newline at end of file
diff --git a/Spear.lkshw b/Spear.lkshw
index 9220bd8..79c18ef 100644
--- a/Spear.lkshw
+++ b/Spear.lkshw
@@ -1,7 +1,7 @@
 Version of workspace file format:
                1
 Time of storage:
-               "Fri Aug 31 18:36:39 CEST 2012"
+               "Fri Aug 31 20:53:49 CEST 2012"
 Name of the workspace:
                "Spear"
 File paths of contained packages:
diff --git a/Spear/Math/MatrixUtils.hs b/Spear/Math/MatrixUtils.hs
index 68ad6cd..2c1d083 100644
--- a/Spear/Math/MatrixUtils.hs
+++ b/Spear/Math/MatrixUtils.hs
@@ -1,6 +1,7 @@
 module Spear.Math.MatrixUtils
 (
-    fastNormalMatrix
+    Rotation(..)
+,   fastNormalMatrix
 ,   rpgTransform
 ,   pltTransform
 ,   rpgInverse
@@ -15,6 +16,9 @@ import Spear.Math.Vector2 as V2
 import Spear.Math.Vector3 as V3
 
 
+data Rotation = Yaw | Pitch | Roll deriving Eq
+
+
 -- | Compute the normal matrix of the given matrix.
 fastNormalMatrix :: Matrix4 -> Matrix3
 fastNormalMatrix m =
@@ -26,13 +30,26 @@ fastNormalMatrix m =
 
 
 -- | Maps the given 2D transformation matrix to a 3D transformation matrix.
-rpgTransform :: Float -- ^ The height above the ground.
-             -> Matrix3 -> Matrix4
-rpgTransform h mat =
-    let r = let r' = M3.right mat in vec3 (V2.x r') (V2.y r') 0
+rpgTransform
+    :: Float    -- ^ The height above the ground.
+    -> Float    -- ^ Angle of rotation.
+    -> Rotation -- ^ How the 2D rotation should be interpreted in 3D.
+    -> Matrix3
+    -> Matrix4
+rpgTransform h a rtype mat =
+    {-let r = let r' = M3.right mat in vec3 (V2.x r') (V2.y r') 0
         u = V3.unity
         f = let f' = M3.forward mat in vec3 (V2.x f') 0 (V2.y f')
-        t = (vec3 0 h 0) + let t' = M3.position mat in vec3 (V2.x t') 0 (V2.y t')
+        t = (vec3 0 h 0) + let t' = M3.position mat in vec3 (V2.x t') 0 (V2.y t')-}
+    let rot = case rtype of
+            Yaw   -> rotY
+            Pitch -> rotX
+            Roll  -> rotZ
+        mat' = rot a
+        r = M4.right mat'
+        u = M4.up mat'
+        f = M4.forward mat'
+        t = vec3 0 h 0 + let t' = M3.position mat in vec3 (V2.x t') 0 (V2.y t')
     in mat4
         (V3.x r) (V3.x u) (V3.x f) (V3.x t)
         (V3.y r) (V3.y u) (V3.y f) (V3.y t)
@@ -61,18 +78,13 @@ pltTransform mat =
 -- The XY plane in 2D translates to the X(-Z) plane in 3D.
 --
 -- Use this in games such as RPGs and RTSs.
-rpgInverse :: Float -- ^ Height above the ground.
-           -> Matrix3 -> Matrix4
-rpgInverse h mat =
-    let r = let r' = M3.right mat in vec3 (V2.x r') (V2.y r') 0
-        u = V3.unity
-        f = let f' = M3.forward mat in vec3 (V2.x f') 0 (-V2.y f')
-        t = (vec3 0 h 0) + let t' = M3.position mat in -(vec3 (V2.x t') 0 (-V2.y t'))
-    in mat4
-        (V3.x r) (V3.y r) (V3.z r) (t `V3.dot` r)
-        (V3.x u) (V3.y u) (V3.z u) (t `V3.dot` u)
-        (V3.x f) (V3.y f) (V3.z f) (t `V3.dot` f)
-        0        0        0        1
+rpgInverse
+    :: Float    -- ^ The height above the ground.
+    -> Float    -- ^ Angle of rotation.
+    -> Rotation -- ^ How the 2D rotation should be interpreted in 3D.
+    -> Matrix3
+    -> Matrix4
+rpgInverse h a rot = M4.inverseTransform . rpgTransform h a rot
 
 
 -- | Compute the inverse transform of the given transformation matrix.
@@ -83,13 +95,4 @@ rpgInverse h mat =
 -- 
 -- Use this in games like platformers and space invaders style games.
 pltInverse :: Matrix3 -> Matrix4
-pltInverse mat =
-    let r = let r' = M3.right mat in vec3 (V2.x r') (V2.y r') 0
-        u = let u' = M3.up mat in vec3 (V2.x u') (V2.y u') 0
-        f = V3.unitz
-        t = let t' = M3.position mat in vec3 (V2.x t') (V2.y t') 0
-    in mat4
-        (V3.x r) (V3.y r) (V3.z r) (t `V3.dot` r)
-        (V3.x u) (V3.y u) (V3.z u) (t `V3.dot` u)
-        (V3.x f) (V3.y f) (V3.z f) (t `V3.dot` f)
-        0        0        0        1
+pltInverse = M4.inverseTransform . pltTransform
diff --git a/Spear/Scene/GameObject.hs b/Spear/Scene/GameObject.hs
index e012122..f29ee09 100644
--- a/Spear/Scene/GameObject.hs
+++ b/Spear/Scene/GameObject.hs
@@ -3,14 +3,16 @@ module Spear.Scene.GameObject
     GameObject
 ,   GameStyle(..)
 ,   AM.AnimationSpeed
+,   Rotation(..)
     -- * Construction
 ,   goNew
     -- * Accessors
-,   renderer
 ,   currentAnimation
-,   numCollisioners
 ,   goAABB
 ,   goAABBs
+,   go3Dtransform
+,   numCollisioners
+,   renderer
     -- * Manipulation
 ,   goUpdate
 ,   setAnimation
@@ -39,6 +41,7 @@ import qualified Spear.Render.AnimatedModel as AM
 import Spear.Render.Program
 import Spear.Render.StaticModel as SM
 
+import Data.Fixed (mod')
 import Data.List (foldl')
 
 
@@ -51,9 +54,11 @@ data GameStyle
 -- | An object in the game scene.
 data GameObject = GameObject
     { gameStyle    :: !GameStyle
+    , rotation     :: !Rotation
     , renderer     :: !(Either StaticModelRenderer AM.AnimatedModelRenderer)
     , collisioners :: ![Collisioner]
     , transform    :: !M3.Matrix3
+    , angle        :: Float
     }
 
 
@@ -96,7 +101,11 @@ instance S2.Spatial2 GameObject where
             , transform = M3.translv v * m
             }
     
-    rotate angle go = go { transform = transform go * M3.rot angle }
+    rotate a go =
+        go
+        { transform = transform go * M3.rot a
+        , angle = (angle go + a) `mod'` 360 
+        }
     
     pos go = M3.position . transform $ go
     
@@ -113,20 +122,31 @@ instance S2.Spatial2 GameObject where
     setPos pos go =
         let m = transform go
         in go { transform = M3.transform (M3.right m) (M3.forward m) pos }
+    
+    lookAt p go =
+        let position = S2.pos go
+            fwd      = V2.normalise $ p - position
+            r        = perp fwd
+        in
+            go
+            { transform = M3.transform r fwd position
+            , angle = acos $ r `V2.dot` V2.unitx
+            }
 
 
 -- | Create a new game object.
 goNew :: GameStyle
+      -> Rotation
       -> Either StaticModelResource AM.AnimatedModelResource
       -> [Collisioner]
       -> M3.Matrix3
       -> GameObject
 
-goNew style (Left smr) cols transf =
-    GameObject style (Left $ SM.staticModelRenderer smr) cols transf
+goNew style rtype (Left smr) cols transf =
+    GameObject style rtype (Left $ SM.staticModelRenderer smr) cols transf 0
 
-goNew style (Right amr) cols transf =
-    GameObject style (Right $ AM.animatedModelRenderer 1 amr) cols transf
+goNew style rtype (Right amr) cols transf =
+    GameObject style rtype (Right $ AM.animatedModelRenderer 1 amr) cols transf 0
 
 
 goUpdate :: Float -> GameObject -> GameObject
@@ -190,6 +210,11 @@ goAABBs :: GameObject -> [AABB]
 goAABBs = fmap goAABB' . collisioners
 
 
+-- | Get the game object's 3D transform.
+go3Dtransform :: GameObject -> M4.Matrix4
+go3Dtransform go = rpgTransform 0 (angle go) (rotation go) . S2.transform $ go
+
+
 -- | Render the game object.
 goRender :: StaticProgram -> AnimatedProgram -> Cam.Camera -> GameObject -> IO ()
 goRender sprog aprog cam go =
@@ -197,9 +222,13 @@ goRender sprog aprog cam go =
         apu = animatedProgramUniforms aprog
         mat = S2.transform go
         style = gameStyle go
+        rtype = rotation go
+        a   = angle go
     in case renderer go of
-        Left smr  -> goRender' style sprog spu mat cam (SM.bind spu smr) (SM.render spu smr)
-        Right amr -> goRender' style aprog apu mat cam (AM.bind apu amr) (AM.render apu amr)
+        Left smr  ->
+            goRender' style a rtype sprog spu mat cam (SM.bind spu smr) (SM.render spu smr)
+        Right amr ->
+            goRender' style a rtype aprog apu mat cam (AM.bind apu amr) (AM.render apu amr)
 
 
 type Bind = IO ()
@@ -209,6 +238,8 @@ type Render = IO ()
 
 goRender' :: (ProgramUniforms u, Program p)
           => GameStyle
+          -> Float
+          -> Rotation
           -> p
           -> u
           -> M3.Matrix3
@@ -216,10 +247,10 @@ goRender' :: (ProgramUniforms u, Program p)
           -> Bind
           -> Render
           -> IO ()
-goRender' style prog uniforms model cam bindRenderer render =
+goRender' style a rtype prog uniforms model cam bindRenderer render =
     let view  = M4.inverseTransform $ Cam.transform cam
         modelview = case style of
-            RPG -> view * rpgTransform 0 model
+            RPG -> view * rpgTransform 0 a rtype model
             PLT -> view * pltTransform model
         normalmat = fastNormalMatrix modelview
     in do
diff --git a/Spear/Scene/Loader.hs b/Spear/Scene/Loader.hs
index e3b9546..ea08385 100644
--- a/Spear/Scene/Loader.hs
+++ b/Spear/Scene/Loader.hs
@@ -31,7 +31,7 @@ import Spear.Render.AnimatedModel as AM
 import Spear.Render.Material
 import Spear.Render.Program
 import Spear.Render.StaticModel as SM
-import Spear.Scene.GameObject as GO
+import qualified Spear.Scene.GameObject as GO
 import Spear.Scene.Graph
 import Spear.Scene.Light
 import Spear.Scene.SceneResources
@@ -342,17 +342,18 @@ newLight _ = return ()
 -- Object Loading --
 --------------------
 
-loadGO :: GameStyle -> SceneResources -> [Property] -> Matrix3 -> Setup GameObject
+loadGO :: GO.GameStyle -> SceneResources -> [Property] -> Matrix3 -> Setup GO.GameObject
 loadGO style sceneRes props transf = do
-    modelName <- asString . mandatory "model" $ props
+    modelName <- asString . mandatory "model"    $ props
+    rtype <- asGORotation . mandatory "rotation" $ props
     let animSpeed = asFloat  . value "animation-speed" $ props
     go <- case getAnimatedModel sceneRes modelName of
         Just model ->
-            return $ goNew style (Right model) [] transf
+            return $ GO.goNew style rtype (Right model) [] transf
         Nothing ->
             case getStaticModel sceneRes modelName of
                 Just model ->
-                    return $ goNew style (Left model) [] transf
+                    return $ GO.goNew style rtype (Left model) [] transf
                 Nothing ->
                     setupError $ "model " ++ modelName ++ " not found"
     return $ case animSpeed of
@@ -466,6 +467,13 @@ asRotation val = fmap parseRotation val
     where parseRotation (ax:ay:az:order:_) = Rotation (read ax) (read ay) (read az) (readOrder order)
 
 
+asGORotation :: Functor f => f [String] -> f GO.Rotation
+asGORotation val = fmap parseRotation val
+    where parseRotation ["yaw"]   = GO.Yaw
+          parseRotation ["pitch"] = GO.Pitch
+          parseRotation ["roll"]  = GO.Roll
+
+
 data Rotation = Rotation
     { ax    :: Float
     , ay    :: Float
-- 
cgit v1.2.3