diff options
-rw-r--r-- | Spear.lkshs | 12 | ||||
-rw-r--r-- | Spear.lkshw | 2 | ||||
-rw-r--r-- | Spear/Assets/Model.hsc | 378 | ||||
-rw-r--r-- | Spear/Assets/Model/Model.c | 56 | ||||
-rw-r--r-- | Spear/Assets/Model/Model.h | 6 | ||||
-rw-r--r-- | Spear/Render/Model.hsc | 4 | ||||
-rw-r--r-- | Spear/Scene/Loader.hs | 37 |
7 files changed, 211 insertions, 284 deletions
diff --git a/Spear.lkshs b/Spear.lkshs index afbce39..d69e4f9 100644 --- a/Spear.lkshs +++ b/Spear.lkshs | |||
@@ -1,18 +1,18 @@ | |||
1 | Version of session file format: | 1 | Version of session file format: |
2 | 1 | 2 | 1 |
3 | Time of storage: | 3 | Time of storage: |
4 | "Thu Aug 9 13:31:29 CEST 2012" | 4 | "Fri Aug 10 15:19:04 CEST 2012" |
5 | Layout: VerticalP (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = 6, 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}) 266) 197)], paneTabs = Just BottomP, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 702) 954 | 5 | 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}) 255) 201)], paneTabs = Just BottomP, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 707) 954 |
6 | Population: [(Just (ErrorsSt ErrorsState),[SplitP RightP,SplitP TopP]),(Just (FilesSt FilesState),[SplitP RightP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/demos/simple-scene/GameObject.hs" 259)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/demos/simple-scene/GameState.hs" 670)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Sys/Store/ID.hs" 96)),[SplitP LeftP]),(Just (InfoSt (InfoState (Just (Real (RealDescr {dscName' = "storeFree", dscMbTypeStr' = Just "storeFree :: Index -> Store a -> Store a", dscMbModu' = Just (PM {pack = PackageIdentifier {pkgName = PackageName "Spear", pkgVersion = Version {versionBranch = [0,1], versionTags = []}}, modu = ModuleName ["Spear","Sys","Store"]}), dscMbLocation' = Just (Location {locationSLine = 101, locationSCol = 1, locationELine = 108, locationECol = 32}), dscMbComment' = Just " Free the given slot.", dscTypeHint' = VariableDescr, dscExported' = True}))))),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP BottomP]),(Just (LogSt LogState),[SplitP RightP,SplitP BottomP]),(Just (ModulesSt (ModulesState 328 (PackageScope False,False) (Just (ModuleName ["Spear","Sys","Store"]),Just "storeFree") (ExpanderState {packageExp = ([],[]), packageExpNoBlack = ([[0,9],[0]],[]), packageDExp = ([],[]), packageDExpNoBlack = ([],[]), workspaceExp = ([],[]), workspaceExpNoBlack = ([[5]],[]), workspaceDExp = ([],[]), workspaceDExpNoBlack = ([],[]), systemExp = ([],[]), systemExpNoBlack = ([],[])}))),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Physics.hs" 207)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Physics/Rigid.hs" 2175)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Sys/Store.hs" 4136)),[SplitP LeftP]),(Just (WorkspaceSt WorkspaceState),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Physics/World.hs" 287)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/demos/simple-scene/main.hs" 204)),[SplitP LeftP])] | 6 | Population: [(Just (ErrorsSt ErrorsState),[SplitP RightP,SplitP TopP]),(Just (FilesSt FilesState),[SplitP RightP,SplitP TopP]),(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" 6686)),[SplitP LeftP]),(Just (LogSt LogState),[SplitP RightP,SplitP BottomP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/MD2/MD2_load.c" 13934)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/Model.c" 433)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/Model.h" 1424)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model.hsc" 12957)),[SplitP LeftP]),(Just (ModulesSt (ModulesState 328 (PackageScope False,False) (Nothing,Nothing) (ExpanderState {packageExp = ([],[]), packageExpNoBlack = ([],[]), packageDExp = ([],[]), packageDExpNoBlack = ([],[]), workspaceExp = ([],[]), workspaceExpNoBlack = ([[0,2],[0]],[]), workspaceDExp = ([],[]), workspaceDExpNoBlack = ([],[]), systemExp = ([],[]), systemExpNoBlack = ([],[])}))),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/OBJ/OBJ_load.cc" 266)),[SplitP LeftP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/OBJ/OBJ_load.h" 0)),[SplitP LeftP]),(Just (WorkspaceSt WorkspaceState),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP TopP])] |
7 | Window size: (1841,964) | 7 | Window size: (1841,964) |
8 | Completion size: | 8 | Completion size: |
9 | (750,400) | 9 | (750,400) |
10 | Workspace: Just "/home/jeanne/programming/haskell/Spear/Spear.lkshw" | 10 | Workspace: Just "/home/jeanne/programming/haskell/Spear/Spear.lkshw" |
11 | Active pane: Just "World.hs" | 11 | Active pane: Just "Model.hsc" |
12 | Toolbar visible: | 12 | Toolbar visible: |
13 | True | 13 | True |
14 | FindbarState: (False,FindState {entryStr = "asda", entryHist = ["assigned","Triangle","transforma","gravity","asdad","rotSpeed","azimuth","mandatory","mandao","col","forward","MouseButton"], replaceStr = "objects", replaceHist = [], caseSensitive = True, entireWord = False, wrapAround = False, regex = False, lineNr = 1}) | 14 | FindbarState: (False,FindState {entryStr = "asd", entryHist = ["allocaBytes","copyArray","allocaArray","allocaa","putStrLn","assigned","Triangle","transforma","gravity","asdad","rotSpeed","azimuth"], replaceStr = "objects", replaceHist = [], caseSensitive = True, entireWord = False, wrapAround = False, regex = False, lineNr = 1}) |
15 | Recently opened files: | 15 | Recently opened files: |
16 | ["/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/Model.h","/home/jeanne/programming/haskell/Spear/Spear/Assets/Model.hsc","/home/jeanne/programming/haskell/Spear/Spear/Math/Spatial.hs","/home/jeanne/programming/haskell/Spear/Spear/Math/Triangle.hs","/home/jeanne/programming/haskell/Spear/Spear/Render/Triangle.hs","/home/jeanne/programming/haskell/Spear/Spear/Assets/Model/Model.c","/home/jeanne/programming/haskell/Spear/Spear/Scene/Loader.hs","/home/jeanne/programming/haskell/Spear/Spear/IDStore.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Spear/IDStore.hs","/home/jeanne/programming/haskell/Spear/Spear/Physics/Types.hs","/home/jeanne/programming/haskell/Spear/Spear/Collision/Collision.hs","/home/jeanne/programming/haskell/Spear/Spear/Collision/Collisioner.hs"] | 16 | ["/home/jeanne/programming/haskell/Spear/Spear/Assets/Image.hsc","/home/jeanne/programming/haskell/Spear/Spear/Render/Model.hsc","/home/jeanne/programming/haskell/Spear/demos/simple-scene/main.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Player.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameState.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameMessage.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Factory.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/Animation/Ogro.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/AnimatedGO.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/StaticGO.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Render.hs"] |
17 | Recently opened workspaces: | 17 | Recently opened workspaces: |
18 | ["/home/jeanne/leksah.lkshw"] \ No newline at end of file | 18 | ["/home/jeanne/leksah.lkshw"] \ No newline at end of file |
diff --git a/Spear.lkshw b/Spear.lkshw index 2291729..143acdc 100644 --- a/Spear.lkshw +++ b/Spear.lkshw | |||
@@ -1,7 +1,7 @@ | |||
1 | Version of workspace file format: | 1 | Version of workspace file format: |
2 | 1 | 2 | 1 |
3 | Time of storage: | 3 | Time of storage: |
4 | "Wed Aug 8 21:04:06 CEST 2012" | 4 | "Fri Aug 10 15:56:20 CEST 2012" |
5 | Name of the workspace: | 5 | Name of the workspace: |
6 | "Spear" | 6 | "Spear" |
7 | File paths of contained packages: | 7 | File paths of contained packages: |
diff --git a/Spear/Assets/Model.hsc b/Spear/Assets/Model.hsc index cb0ef3f..b7cb90d 100644 --- a/Spear/Assets/Model.hsc +++ b/Spear/Assets/Model.hsc | |||
@@ -3,28 +3,20 @@ | |||
3 | module Spear.Assets.Model | 3 | module Spear.Assets.Model |
4 | ( | 4 | ( |
5 | -- * Data types | 5 | -- * Data types |
6 | ModelErrorCode | 6 | Vec3(..) |
7 | , Vec3(..) | ||
8 | , TexCoord(..) | 7 | , TexCoord(..) |
9 | , CModel | 8 | , CTriangle(..) |
9 | , Skin(..) | ||
10 | , Animation(..) | 10 | , Animation(..) |
11 | , Triangle(..) | 11 | , Triangle(..) |
12 | , Model | 12 | , Model(..) |
13 | -- * Loading and unloading | 13 | -- * Loading |
14 | , loadModel | 14 | , loadModel |
15 | , releaseModel | ||
16 | -- * Accessors | 15 | -- * Accessors |
17 | , animated | 16 | , animated |
18 | , numFrames | ||
19 | , numVertices | ||
20 | , numTriangles | ||
21 | , numTexCoords | ||
22 | , numSkins | ||
23 | , cmodel | ||
24 | , animation | 17 | , animation |
25 | , animationByName | 18 | , animationByName |
26 | , numAnimations | 19 | , triangles' |
27 | , triangles | ||
28 | -- * Manipulation | 20 | -- * Manipulation |
29 | , transformVerts | 21 | , transformVerts |
30 | , transformNormals | 22 | , transformNormals |
@@ -34,15 +26,12 @@ where | |||
34 | 26 | ||
35 | 27 | ||
36 | import Spear.Setup | 28 | import Spear.Setup |
37 | import qualified Spear.Math.Matrix4 as M4 | ||
38 | import qualified Spear.Math.Matrix3 as M3 | ||
39 | import Spear.Math.MatrixUtils | ||
40 | 29 | ||
41 | 30 | ||
42 | import qualified Data.ByteString.Char8 as B | 31 | import qualified Data.ByteString.Char8 as B |
43 | import Data.Char (toLower) | 32 | import Data.Char (toLower) |
44 | import Data.List (splitAt, elemIndex) | 33 | import Data.List (splitAt, elemIndex) |
45 | import qualified Data.Vector as V | 34 | import qualified Data.Vector.Storable as V |
46 | import Foreign.Ptr | 35 | import Foreign.Ptr |
47 | import Foreign.Storable | 36 | import Foreign.Storable |
48 | import Foreign.C.Types | 37 | import Foreign.C.Types |
@@ -69,10 +58,11 @@ data ModelErrorCode | |||
69 | 58 | ||
70 | 59 | ||
71 | sizeFloat = #{size float} | 60 | sizeFloat = #{size float} |
61 | sizePtr = #{size int*} | ||
72 | 62 | ||
73 | 63 | ||
74 | -- | A 3D vector. | 64 | -- | A 3D vector. |
75 | data Vec3 = Vec3 !CFloat !CFloat !CFloat | 65 | data Vec3 = Vec3 !Float !Float !Float |
76 | 66 | ||
77 | 67 | ||
78 | instance Storable Vec3 where | 68 | instance Storable Vec3 where |
@@ -92,7 +82,7 @@ instance Storable Vec3 where | |||
92 | 82 | ||
93 | 83 | ||
94 | -- | A 2D texture coordinate. | 84 | -- | A 2D texture coordinate. |
95 | data TexCoord = TexCoord !CFloat !CFloat | 85 | data TexCoord = TexCoord !Float !Float |
96 | 86 | ||
97 | 87 | ||
98 | instance Storable TexCoord where | 88 | instance Storable TexCoord where |
@@ -109,97 +99,154 @@ instance Storable TexCoord where | |||
109 | pokeByteOff ptr sizeFloat f1 | 99 | pokeByteOff ptr sizeFloat f1 |
110 | 100 | ||
111 | 101 | ||
112 | data CTriangle = CTriangle !CUShort !CUShort !CUShort !CUShort !CUShort !CUShort | 102 | -- | A raw triangle holding vertex/normal and texture indices. |
103 | data CTriangle = CTriangle | ||
104 | { vertexIndex0 :: !CUShort | ||
105 | , vertexIndex1 :: !CUShort | ||
106 | , vertexIndex2 :: !CUShort | ||
107 | , textureIndex1 :: !CUShort | ||
108 | , textureIndex2 :: !CUShort | ||
109 | , textureIndex3 :: !CUShort | ||
110 | } | ||
113 | 111 | ||
114 | 112 | ||
115 | data Skin = Skin !(Ptr Char) | 113 | instance Storable CTriangle where |
114 | sizeOf _ = #{size triangle} | ||
115 | alignment _ = alignment (undefined :: CUShort) | ||
116 | |||
117 | peek ptr = do | ||
118 | v0 <- #{peek triangle, vertexIndices[0]} ptr | ||
119 | v1 <- #{peek triangle, vertexIndices[1]} ptr | ||
120 | v2 <- #{peek triangle, vertexIndices[2]} ptr | ||
121 | |||
122 | t0 <- #{peek triangle, textureIndices[0]} ptr | ||
123 | t1 <- #{peek triangle, textureIndices[1]} ptr | ||
124 | t2 <- #{peek triangle, textureIndices[2]} ptr | ||
125 | |||
126 | return $ CTriangle v0 v1 v2 t0 t1 t2 | ||
127 | |||
128 | poke ptr (CTriangle v0 v1 v2 t0 t1 t2) = do | ||
129 | #{poke triangle, vertexIndices[0]} ptr v0 | ||
130 | #{poke triangle, vertexIndices[1]} ptr v1 | ||
131 | #{poke triangle, vertexIndices[2]} ptr v2 | ||
132 | |||
133 | #{poke triangle, textureIndices[0]} ptr t0 | ||
134 | #{poke triangle, textureIndices[1]} ptr t1 | ||
135 | #{poke triangle, textureIndices[2]} ptr t2 | ||
116 | 136 | ||
117 | 137 | ||
118 | data CAnimation = CAnimation !B.ByteString !CUInt !CUInt | 138 | -- | A model skin. |
139 | newtype Skin = Skin { skinName :: B.ByteString } | ||
119 | 140 | ||
120 | 141 | ||
121 | -- | The model's underlying representation. | 142 | instance Storable Skin where |
122 | data CModel = CModel | 143 | sizeOf (Skin s) = 64 |
123 | { cVerts :: Ptr Vec3 -- ^ Pointer to an array of 'cnFrames' * 'cnVerts' vertices. | 144 | alignment _ = 1 |
124 | , cNormals :: Ptr Vec3 -- ^ Pointer to an array of 'cnFrames' * cnVerts normals. | 145 | |
125 | , cTexCoords :: Ptr TexCoord -- ^ Pointer to an array of 'cnTris' texture coordinates. | 146 | peek ptr = do |
126 | , cTris :: Ptr CTriangle -- ^ Pointer to an array of 'cnTris' triangles. | 147 | s <- B.packCString $ unsafeCoerce ptr |
127 | , cSkins :: Ptr Skin -- ^ Pointer to an array of 'cnSkins' skins. | 148 | return $ Skin s |
128 | , cAnimations :: Ptr CAnimation -- ^ Pointer to an array of 'cnAnimations' animations. | 149 | |
129 | , cnFrames :: CUInt -- ^ Number of frames. | 150 | poke ptr (Skin s) = do |
130 | , cnVerts :: CUInt -- ^ Number of vertices per frame. | 151 | B.useAsCStringLen s $ \(sptr, len) -> copyArray (unsafeCoerce ptr) sptr len |
131 | , cnTris :: CUInt -- ^ Number of triangles in one frame. | ||
132 | , cnTexCoords :: CUInt -- ^ Number of texture coordinates in one frame. | ||
133 | , cnSkins :: CUInt -- ^ Number of skins. | ||
134 | , cnAnimations :: CUInt -- ^ Number of animations. | ||
135 | } | ||
136 | 152 | ||
137 | 153 | ||
138 | instance Storable CModel where | 154 | -- | A model animation. |
139 | sizeOf _ = #{size Model} | 155 | -- |
140 | alignment _ = alignment (undefined :: CUInt) | 156 | -- See also: 'animation', 'animationByName', 'numAnimations'. |
157 | data Animation = Animation | ||
158 | { name :: B.ByteString | ||
159 | , start :: Int | ||
160 | , end :: Int | ||
161 | } | ||
141 | 162 | ||
142 | peek ptr = do | ||
143 | vertices <- #{peek Model, vertices} ptr | ||
144 | normals <- #{peek Model, normals} ptr | ||
145 | texCoords <- #{peek Model, texCoords} ptr | ||
146 | triangles <- #{peek Model, triangles} ptr | ||
147 | skins <- #{peek Model, skins} ptr | ||
148 | animations <- #{peek Model, animations} ptr | ||
149 | numFrames <- #{peek Model, numFrames} ptr | ||
150 | numVertices <- #{peek Model, numVertices} ptr | ||
151 | numTriangles <- #{peek Model, numTriangles} ptr | ||
152 | numTexCoords <- #{peek Model, numTexCoords} ptr | ||
153 | numSkins <- #{peek Model, numSkins} ptr | ||
154 | numAnimations <- #{peek Model, numAnimations} ptr | ||
155 | return $ | ||
156 | CModel vertices normals texCoords triangles skins animations | ||
157 | numFrames numVertices numTriangles numTexCoords numSkins numAnimations | ||
158 | 163 | ||
159 | poke ptr | 164 | instance Storable Animation where |
160 | (CModel verts normals texCoords tris skins animations | ||
161 | numFrames numVerts numTris numTex numSkins numAnimations) = do | ||
162 | #{poke Model, vertices} ptr verts | ||
163 | #{poke Model, normals} ptr normals | ||
164 | #{poke Model, texCoords} ptr texCoords | ||
165 | #{poke Model, triangles} ptr tris | ||
166 | #{poke Model, skins} ptr skins | ||
167 | #{poke Model, animations} ptr animations | ||
168 | #{poke Model, numFrames} ptr numFrames | ||
169 | #{poke Model, numVertices} ptr numVerts | ||
170 | #{poke Model, numTriangles} ptr numTris | ||
171 | #{poke Model, numTexCoords} ptr numTex | ||
172 | #{poke Model, numSkins} ptr numSkins | ||
173 | #{poke Model, numAnimations} ptr numAnimations | ||
174 | |||
175 | |||
176 | -- data CAnimation = CAnimation !(Ptr CChar) !CUInt !CUInt | ||
177 | instance Storable CAnimation where | ||
178 | sizeOf _ = #{size animation} | 165 | sizeOf _ = #{size animation} |
179 | alignment _ = alignment (undefined :: CUInt) | 166 | alignment _ = alignment (undefined :: CUInt) |
180 | 167 | ||
181 | peek ptr = do | 168 | peek ptr = do |
182 | name <- B.packCString (unsafeCoerce ptr) | 169 | name <- B.packCString (unsafeCoerce ptr) |
183 | start <- #{peek animation, start} ptr | 170 | start <- #{peek animation, start} ptr |
184 | end <- #{peek animation, end} ptr | 171 | end <- #{peek animation, end} ptr |
185 | return $ CAnimation name start end | 172 | return $ Animation name start end |
186 | 173 | ||
187 | poke ptr (CAnimation name start end) = do | 174 | poke ptr (Animation name start end) = do |
188 | B.useAsCStringLen name $ \(sptr, len) -> copyArray (unsafeCoerce ptr) sptr len | 175 | B.useAsCStringLen name $ \(sptr, len) -> copyArray (unsafeCoerce ptr) sptr len |
189 | #{poke animation, start} ptr start | 176 | #{poke animation, start} ptr start |
190 | #{poke animation, end} ptr end | 177 | #{poke animation, end} ptr end |
191 | 178 | ||
192 | 179 | ||
193 | -- | A model's animation. | 180 | -- | A 3D model. |
194 | -- | 181 | data Model = Model |
195 | -- See also: 'animation', 'animationByName', 'numAnimations'. | 182 | { vertices :: V.Vector Vec3 -- ^ Array of 'numFrames' * 'numVerts' vertices. |
196 | data Animation = Animation | 183 | , normals :: V.Vector Vec3 -- ^ Array of 'numFrames' * 'numVerts' normals. |
197 | { name :: String | 184 | , texCoords :: V.Vector TexCoord -- ^ Array of 'numTexCoords' texture coordinates. |
198 | , start :: Int | 185 | , triangles :: V.Vector CTriangle -- ^ Array of 'numTriangles' triangles. |
199 | , end :: Int | 186 | , skins :: V.Vector Skin -- ^ Array of 'numSkins' skins. |
187 | , animations :: V.Vector Animation -- ^ Array of 'numAnimations' animations. | ||
188 | , numFrames :: Int -- ^ Number of frames. | ||
189 | , numVerts :: Int -- ^ Number of vertices (and normals) per frame. | ||
190 | , numTriangles :: Int -- ^ Number of triangles in one frame. | ||
191 | , numTexCoords :: Int -- ^ Number of texture coordinates in one frame. | ||
192 | , numSkins :: Int -- ^ Number of skins. | ||
193 | , numAnimations :: Int -- ^ Number of animations. | ||
200 | } | 194 | } |
201 | 195 | ||
202 | 196 | ||
197 | instance Storable Model where | ||
198 | sizeOf _ = #{size Model} | ||
199 | alignment _ = alignment (undefined :: CUInt) | ||
200 | |||
201 | peek ptr = do | ||
202 | numFrames <- #{peek Model, numFrames} ptr | ||
203 | numVertices <- #{peek Model, numVertices} ptr | ||
204 | numTriangles <- #{peek Model, numTriangles} ptr | ||
205 | numTexCoords <- #{peek Model, numTexCoords} ptr | ||
206 | numSkins <- #{peek Model, numSkins} ptr | ||
207 | numAnimations <- #{peek Model, numAnimations} ptr | ||
208 | pVerts <- peek (unsafeCoerce ptr) | ||
209 | pNormals <- peekByteOff ptr sizePtr | ||
210 | pTexCoords <- peekByteOff ptr (2*sizePtr) | ||
211 | pTriangles <- peekByteOff ptr (3*sizePtr) | ||
212 | pSkins <- peekByteOff ptr (4*sizePtr) | ||
213 | pAnimations <- peekByteOff ptr (5*sizePtr) | ||
214 | vertices <- fmap V.fromList $ peekArray (numVertices*numFrames) pVerts | ||
215 | normals <- fmap V.fromList $ peekArray (numVertices*numFrames) pNormals | ||
216 | texCoords <- fmap V.fromList $ peekArray numTexCoords pTexCoords | ||
217 | triangles <- fmap V.fromList $ peekArray numTriangles pTriangles | ||
218 | skins <- fmap V.fromList $ peekArray numSkins pSkins | ||
219 | animations <- fmap V.fromList $ peekArray numAnimations pAnimations | ||
220 | return $ | ||
221 | Model vertices normals texCoords triangles skins animations | ||
222 | numFrames numVertices numTriangles numTexCoords numSkins numAnimations | ||
223 | |||
224 | poke ptr | ||
225 | (Model verts normals texCoords tris skins animations | ||
226 | numFrames numVerts numTris numTex numSkins numAnimations) = | ||
227 | V.unsafeWith verts $ \pVerts -> | ||
228 | V.unsafeWith normals $ \pNormals -> | ||
229 | V.unsafeWith texCoords $ \pTexCoords -> | ||
230 | V.unsafeWith tris $ \pTris -> | ||
231 | V.unsafeWith skins $ \pSkins -> | ||
232 | V.unsafeWith animations $ \pAnimations -> do | ||
233 | #{poke Model, vertices} ptr pVerts | ||
234 | #{poke Model, normals} ptr pNormals | ||
235 | #{poke Model, texCoords} ptr pTexCoords | ||
236 | #{poke Model, triangles} ptr pTris | ||
237 | #{poke Model, skins} ptr pSkins | ||
238 | #{poke Model, animations} ptr pAnimations | ||
239 | #{poke Model, numFrames} ptr numFrames | ||
240 | #{poke Model, numVertices} ptr numVerts | ||
241 | #{poke Model, numTriangles} ptr numTris | ||
242 | #{poke Model, numTexCoords} ptr numTex | ||
243 | #{poke Model, numSkins} ptr numSkins | ||
244 | #{poke Model, numAnimations} ptr numAnimations | ||
245 | |||
246 | |||
247 | -- | A model triangle. | ||
248 | -- | ||
249 | -- See also: 'triangles''. | ||
203 | data Triangle = Triangle | 250 | data Triangle = Triangle |
204 | { v0 :: Vec3 | 251 | { v0 :: Vec3 |
205 | , v1 :: Vec3 | 252 | , v1 :: Vec3 |
@@ -241,87 +288,58 @@ instance Storable Triangle where | |||
241 | #{poke model_triangle, t2} ptr t2 | 288 | #{poke model_triangle, t2} ptr t2 |
242 | 289 | ||
243 | 290 | ||
244 | -- | A model 'Resource'. | ||
245 | data Model = Model | ||
246 | { modelData :: CModel | ||
247 | , mAnimations :: V.Vector Animation | ||
248 | , rkey :: Resource | ||
249 | } | ||
250 | |||
251 | |||
252 | foreign import ccall "Model.h model_free" | 291 | foreign import ccall "Model.h model_free" |
253 | model_free :: Ptr CModel -> IO () | 292 | model_free :: Ptr Model -> IO () |
254 | 293 | ||
255 | 294 | ||
256 | foreign import ccall "MD2_load.h MD2_load" | 295 | foreign import ccall "MD2_load.h MD2_load" |
257 | md2_load' :: Ptr CChar -> CChar -> CChar -> Ptr CModel -> IO Int | 296 | md2_load' :: Ptr CChar -> CChar -> CChar -> Ptr Model -> IO Int |
258 | 297 | ||
259 | 298 | ||
260 | foreign import ccall "OBJ_load.h OBJ_load" | 299 | foreign import ccall "OBJ_load.h OBJ_load" |
261 | obj_load' :: Ptr CChar -> CChar -> CChar -> Ptr CModel -> IO Int | 300 | obj_load' :: Ptr CChar -> CChar -> CChar -> Ptr Model -> IO Int |
262 | 301 | ||
263 | 302 | ||
264 | md2_load :: Ptr CChar -> CChar -> CChar -> Ptr CModel -> IO ModelErrorCode | 303 | md2_load :: Ptr CChar -> CChar -> CChar -> Ptr Model -> IO ModelErrorCode |
265 | md2_load file clockwise leftHanded model = | 304 | md2_load file clockwise leftHanded model = |
266 | md2_load' file clockwise leftHanded model >>= \code -> return . toEnum $ code | 305 | md2_load' file clockwise leftHanded model >>= \code -> return . toEnum $ code |
267 | 306 | ||
268 | 307 | ||
269 | obj_load :: Ptr CChar -> CChar -> CChar -> Ptr CModel -> IO ModelErrorCode | 308 | obj_load :: Ptr CChar -> CChar -> CChar -> Ptr Model -> IO ModelErrorCode |
270 | obj_load file clockwise leftHanded model = | 309 | obj_load file clockwise leftHanded model = |
271 | obj_load' file clockwise leftHanded model >>= \code -> return . toEnum $ code | 310 | obj_load' file clockwise leftHanded model >>= \code -> return . toEnum $ code |
272 | 311 | ||
273 | 312 | ||
274 | -- | Load the model specified by the given 'FilePath'. | 313 | -- | Load the model specified by the given file. |
275 | loadModel :: FilePath -> Setup Model | 314 | loadModel :: FilePath -> Setup Model |
276 | loadModel file = do | 315 | loadModel file = do |
277 | dotPos <- case elemIndex '.' file of | 316 | dotPos <- case elemIndex '.' file of |
278 | Nothing -> setupError $ "file name has no extension: " ++ file | 317 | Nothing -> setupError $ "file name has no extension: " ++ file |
279 | Just p -> return p | 318 | Just p -> return p |
280 | 319 | ||
281 | let ext = map toLower . tail . snd $ splitAt dotPos file | 320 | let ext = map toLower . tail . snd $ splitAt dotPos file |
282 | 321 | ||
283 | result <- setupIO . alloca $ \ptr -> do | 322 | result <- setupIO . alloca $ \ptr -> do |
284 | status <- withCString file $ \fileCstr -> do | 323 | status <- withCString file $ \fileCstr -> do |
285 | case ext of | 324 | case ext of |
286 | "md2" -> md2_load fileCstr 0 0 ptr | 325 | "md2" -> md2_load fileCstr 0 0 ptr |
287 | "obj" -> obj_load fileCstr 0 0 ptr | 326 | "obj" -> obj_load fileCstr 0 0 ptr |
288 | _ -> return ModelNoSuitableLoader | 327 | _ -> return ModelNoSuitableLoader |
289 | 328 | ||
290 | case status of | 329 | case status of |
291 | ModelSuccess -> peek ptr >>= return . Right | 330 | ModelSuccess -> do |
331 | model <- peek ptr | ||
332 | model_free ptr | ||
333 | return . Right $ model | ||
292 | ModelReadError -> return . Left $ "read error" | 334 | ModelReadError -> return . Left $ "read error" |
293 | ModelMemoryAllocationError -> return . Left $ "memory allocation error" | 335 | ModelMemoryAllocationError -> return . Left $ "memory allocation error" |
294 | ModelFileNotFound -> return . Left $ "file not found" | 336 | ModelFileNotFound -> return . Left $ "file not found" |
295 | ModelFileMismatch -> return . Left $ "file mismatch" | 337 | ModelFileMismatch -> return . Left $ "file mismatch" |
296 | ModelNoSuitableLoader -> return . Left $ "no suitable loader for extension " ++ ext | 338 | ModelNoSuitableLoader -> return . Left $ "no suitable loader for extension " ++ ext |
297 | 339 | ||
298 | case result of | 340 | case result of |
299 | Right model -> | 341 | Right model -> return model |
300 | let numAnimations = fromIntegral $ cnAnimations model | 342 | Left err -> setupError $ "loadModel: " ++ err |
301 | in register (freeModel model) >>= | ||
302 | case numAnimations of | ||
303 | 0 -> return . Model model V.empty | ||
304 | _ -> \key -> setupIO $ do | ||
305 | canims <- peekArray numAnimations $ cAnimations model | ||
306 | let animations = V.fromList $ fmap fromCAnimation canims | ||
307 | return $ Model model animations key | ||
308 | |||
309 | Left err -> setupError $ "loadModel: " ++ err | ||
310 | |||
311 | |||
312 | fromCAnimation :: CAnimation -> Animation | ||
313 | fromCAnimation (CAnimation cname start end) = | ||
314 | Animation (B.unpack cname) (fromIntegral start) (fromIntegral end) | ||
315 | |||
316 | |||
317 | -- | Release the model. | ||
318 | releaseModel :: Model -> Setup () | ||
319 | releaseModel = release . rkey | ||
320 | |||
321 | |||
322 | -- | Free the C model. | ||
323 | freeModel :: CModel -> IO () | ||
324 | freeModel model = Foreign.with model model_free | ||
325 | 343 | ||
326 | 344 | ||
327 | -- | Return 'True' if the model is animated, 'False' otherwise. | 345 | -- | Return 'True' if the model is animated, 'False' otherwise. |
@@ -329,55 +347,21 @@ animated :: Model -> Bool | |||
329 | animated = (>1) . numFrames | 347 | animated = (>1) . numFrames |
330 | 348 | ||
331 | 349 | ||
332 | -- | Return the model's number of frames. | ||
333 | numFrames :: Model -> Int | ||
334 | numFrames = fromIntegral . cnFrames . modelData | ||
335 | |||
336 | |||
337 | -- | Return the model's number of vertices. | ||
338 | numVertices :: Model -> Int | ||
339 | numVertices = fromIntegral . cnVerts . modelData | ||
340 | |||
341 | |||
342 | -- | Return the model's number of triangles. | ||
343 | numTriangles :: Model -> Int | ||
344 | numTriangles = fromIntegral . cnTris . modelData | ||
345 | |||
346 | |||
347 | -- | Return the model's number of texture coordinates. | ||
348 | numTexCoords :: Model -> Int | ||
349 | numTexCoords = fromIntegral . cnTexCoords . modelData | ||
350 | |||
351 | |||
352 | -- | Return the model's number of skins. | ||
353 | numSkins :: Model -> Int | ||
354 | numSkins = fromIntegral . cnSkins . modelData | ||
355 | |||
356 | |||
357 | -- | Return the underlying C model. | ||
358 | cmodel :: Model -> CModel | ||
359 | cmodel = modelData | ||
360 | |||
361 | |||
362 | -- | Return the model's ith animation. | 350 | -- | Return the model's ith animation. |
363 | animation :: Model -> Int -> Animation | 351 | animation :: Model -> Int -> Animation |
364 | animation model i = mAnimations model V.! i | 352 | animation model i = animations model V.! i |
365 | 353 | ||
366 | 354 | ||
367 | -- | Return the animation specified by the given string. | 355 | -- | Return the animation specified by the given string. |
368 | animationByName :: Model -> String -> Maybe Animation | 356 | animationByName :: Model -> String -> Maybe Animation |
369 | animationByName model anim = V.find ((==) anim . name) $ mAnimations model | 357 | animationByName model anim = |
370 | 358 | let anim' = B.pack anim in V.find ((==) anim' . name) $ animations model | |
371 | |||
372 | -- | Return the number of animations of the given model. | ||
373 | numAnimations :: Model -> Int | ||
374 | numAnimations = V.length . mAnimations | ||
375 | 359 | ||
376 | 360 | ||
377 | -- | Return a copy of the model's triangles. | 361 | -- | Return a copy of the model's triangles. |
378 | triangles :: Model -> IO [Triangle] | 362 | triangles' :: Model -> IO [Triangle] |
379 | triangles m@(Model model _ _) = | 363 | triangles' model = |
380 | let n = numVertices m * numFrames m | 364 | let n = numVerts model * numFrames model |
381 | in with model $ \modelPtr -> | 365 | in with model $ \modelPtr -> |
382 | allocaArray n $ \arrayPtr -> do | 366 | allocaArray n $ \arrayPtr -> do |
383 | model_copy_triangles modelPtr arrayPtr | 367 | model_copy_triangles modelPtr arrayPtr |
@@ -386,39 +370,35 @@ triangles m@(Model model _ _) = | |||
386 | 370 | ||
387 | 371 | ||
388 | foreign import ccall "Model.h model_copy_triangles" | 372 | foreign import ccall "Model.h model_copy_triangles" |
389 | model_copy_triangles :: Ptr CModel -> Ptr Triangle -> IO () | 373 | model_copy_triangles :: Ptr Model -> Ptr Triangle -> IO () |
390 | |||
391 | |||
392 | -- | Transform the model's vertices with the given matrix. | ||
393 | transformVerts :: M4.Matrix4 -> Model -> IO () | ||
394 | transformVerts mat (Model model _ _) = | ||
395 | allocaBytes (16*sizeFloat) $ \matPtr -> | ||
396 | with model $ \modelPtr -> do | ||
397 | poke matPtr mat | ||
398 | model_transform_vertices modelPtr matPtr | ||
399 | |||
400 | |||
401 | -- | Transform the model's normals with the given matrix. | ||
402 | transformNormals :: M3.Matrix3 -> Model -> IO () | ||
403 | transformNormals mat (Model model _ _) = | ||
404 | allocaBytes (9*sizeFloat) $ \normalPtr -> | ||
405 | with model $ \modelPtr -> do | ||
406 | poke normalPtr mat | ||
407 | model_transform_normals modelPtr normalPtr | ||
408 | 374 | ||
409 | 375 | ||
410 | foreign import ccall "Model.h model_transform_vertices" | 376 | -- | Transform the model's vertices. |
411 | model_transform_vertices :: Ptr CModel -> Ptr M4.Matrix4 -> IO () | 377 | transformVerts :: Model -> (Vec3 -> Vec3) -> Model |
378 | transformVerts model f = model { vertices = vertices' } | ||
379 | where | ||
380 | n = numVerts model * numFrames model | ||
381 | vertices' = V.generate n f' | ||
382 | f' i = f $ vertices model V.! i | ||
412 | 383 | ||
413 | 384 | ||
414 | foreign import ccall "Model.h model_transform_normals" | 385 | -- | Transform the model's normals. |
415 | model_transform_normals :: Ptr CModel -> Ptr M3.Matrix3 -> IO () | 386 | transformNormals :: Model -> (Vec3 -> Vec3) -> Model |
387 | transformNormals model f = model { normals = normals' } | ||
388 | where | ||
389 | n = numVerts model * numFrames model | ||
390 | normals' = V.generate n f' | ||
391 | f' i = f $ normals model V.! i | ||
416 | 392 | ||
417 | 393 | ||
418 | -- | Transform the model such that its lowest point has y = 0. | 394 | -- | Translate the model such that its lowest point has y = 0. |
419 | toGround :: Model -> IO () | 395 | toGround :: Model -> IO Model |
420 | toGround (Model model _ _) = with model model_to_ground | 396 | toGround model = |
397 | let model' = model { vertices = V.generate n $ \i -> vertices model V.! i } | ||
398 | n = numVerts model * numFrames model | ||
399 | in | ||
400 | with model' model_to_ground >> return model' | ||
421 | 401 | ||
422 | 402 | ||
423 | foreign import ccall "Model.h model_to_ground" | 403 | foreign import ccall "Model.h model_to_ground" |
424 | model_to_ground :: Ptr CModel -> IO () | 404 | model_to_ground :: Ptr Model -> IO () |
diff --git a/Spear/Assets/Model/Model.c b/Spear/Assets/Model/Model.c index eb955de..4942566 100644 --- a/Spear/Assets/Model/Model.c +++ b/Spear/Assets/Model/Model.c | |||
@@ -27,62 +27,6 @@ void model_free (Model* model) | |||
27 | } | 27 | } |
28 | 28 | ||
29 | 29 | ||
30 | static void mul (float m[16], vec3* v) | ||
31 | { | ||
32 | float x = v->x; | ||
33 | float y = v->y; | ||
34 | float z = v->z; | ||
35 | v->x = x*m[0] + y*m[4] + z*m[8] + m[12]; | ||
36 | v->y = x*m[1] + y*m[5] + z*m[9] + m[13]; | ||
37 | v->z = x*m[2] + y*m[6] + z*m[10] + m[14]; | ||
38 | } | ||
39 | |||
40 | |||
41 | static void mul_normal (float m[9], vec3* n) | ||
42 | { | ||
43 | float x = n->x; | ||
44 | float y = n->y; | ||
45 | float z = n->z; | ||
46 | n->x = x*m[0] + y*m[3] + z*m[6]; | ||
47 | n->y = x*m[1] + y*m[4] + z*m[7]; | ||
48 | n->z = x*m[2] + y*m[5] + z*m[8]; | ||
49 | x = n->x; | ||
50 | y = n->y; | ||
51 | z = n->z; | ||
52 | float mag = sqrt(x*x + y*y + z*z); | ||
53 | mag = mag == 0.0 ? 1.0 : mag; | ||
54 | n->x /= mag; | ||
55 | n->y /= mag; | ||
56 | n->z /= mag; | ||
57 | } | ||
58 | |||
59 | |||
60 | void model_transform_vertices (Model* model, float mat[16]) | ||
61 | { | ||
62 | unsigned i = 0; | ||
63 | unsigned j = model->numVertices * model->numFrames; | ||
64 | vec3* v = model->vertices; | ||
65 | |||
66 | for (; i < j; ++i, ++v) | ||
67 | { | ||
68 | mul (mat, v); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | |||
73 | void model_transform_normals (Model* model, float normal[9]) | ||
74 | { | ||
75 | unsigned i = 0; | ||
76 | unsigned j = model->numVertices * model->numFrames; | ||
77 | vec3* n = model->normals; | ||
78 | |||
79 | for (; i < j; ++i, ++n) | ||
80 | { | ||
81 | mul_normal (normal, n); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | |||
86 | void model_to_ground (Model* model) | 30 | void model_to_ground (Model* model) |
87 | { | 31 | { |
88 | unsigned i, f; | 32 | unsigned i, f; |
diff --git a/Spear/Assets/Model/Model.h b/Spear/Assets/Model/Model.h index 275b040..0532322 100644 --- a/Spear/Assets/Model/Model.h +++ b/Spear/Assets/Model/Model.h | |||
@@ -84,12 +84,6 @@ extern "C" { | |||
84 | /// The 'model' pointer itself is not freed. | 84 | /// The 'model' pointer itself is not freed. |
85 | void model_free (Model* model); | 85 | void model_free (Model* model); |
86 | 86 | ||
87 | /// Transform the Model's vertices by the given matrix. | ||
88 | void model_transform_verts (Model* model, float mat[16]); | ||
89 | |||
90 | /// Transform the Model's normals by the given matrix. | ||
91 | void model_transform_normals (Model* model, float normal[9]); | ||
92 | |||
93 | /// Translate the Model such that its lowest point has y = 0. | 87 | /// Translate the Model such that its lowest point has y = 0. |
94 | void model_to_ground (Model* model); | 88 | void model_to_ground (Model* model); |
95 | 89 | ||
diff --git a/Spear/Render/Model.hsc b/Spear/Render/Model.hsc index 02a37ae..b6c561b 100644 --- a/Spear/Render/Model.hsc +++ b/Spear/Render/Model.hsc | |||
@@ -51,11 +51,11 @@ instance Storable RenderModel where | |||
51 | 51 | ||
52 | 52 | ||
53 | foreign import ccall "RenderModel.h render_model_from_model_asset" | 53 | foreign import ccall "RenderModel.h render_model_from_model_asset" |
54 | render_model_from_model_asset :: Ptr Assets.CModel -> Ptr RenderModel -> IO Int | 54 | render_model_from_model_asset :: Ptr Assets.Model -> Ptr RenderModel -> IO Int |
55 | 55 | ||
56 | 56 | ||
57 | -- | Convert the given 'Model' to a 'ModelData' instance. | 57 | -- | Convert the given 'Model' to a 'ModelData' instance. |
58 | renderModelFromModel :: Assets.Model -> IO RenderModel | 58 | renderModelFromModel :: Assets.Model -> IO RenderModel |
59 | renderModelFromModel m = with (Assets.cmodel m) $ \mPtr -> alloca $ \mdPtr -> do | 59 | renderModelFromModel m = with m $ \mPtr -> alloca $ \mdPtr -> do |
60 | render_model_from_model_asset mPtr mdPtr | 60 | render_model_from_model_asset mPtr mdPtr |
61 | peek mdPtr | 61 | peek mdPtr |
diff --git a/Spear/Scene/Loader.hs b/Spear/Scene/Loader.hs index 06e0aa9..64e81f1 100644 --- a/Spear/Scene/Loader.hs +++ b/Spear/Scene/Loader.hs | |||
@@ -19,6 +19,7 @@ where | |||
19 | 19 | ||
20 | import Spear.Assets.Model as Model | 20 | import Spear.Assets.Model as Model |
21 | import qualified Spear.GLSL as GLSL | 21 | import qualified Spear.GLSL as GLSL |
22 | import qualified Spear.Math.Matrix3 as M3 | ||
22 | import Spear.Math.Matrix4 as M4 | 23 | import Spear.Math.Matrix4 as M4 |
23 | import Spear.Math.MatrixUtils (fastNormalMatrix) | 24 | import Spear.Math.MatrixUtils (fastNormalMatrix) |
24 | import Spear.Math.Vector3 as V3 | 25 | import Spear.Math.Vector3 as V3 |
@@ -188,19 +189,21 @@ newModel (SceneLeaf _ props) = do | |||
188 | 189 | ||
189 | loadModel' :: FilePath -> Maybe Rotation -> Maybe Vector3 -> Setup Model | 190 | loadModel' :: FilePath -> Maybe Rotation -> Maybe Vector3 -> Setup Model |
190 | loadModel' file rotation scale = do | 191 | loadModel' file rotation scale = do |
191 | model <- Model.loadModel file | 192 | let transform = |
192 | case rotation of | 193 | (case rotation of |
193 | Just rot -> setupIO $ rotateModel model rot | 194 | Nothing -> Prelude.id |
194 | Nothing -> return () | 195 | Just rot -> rotateModel rot) . |
195 | case scale of | 196 | |
196 | Just s -> setupIO $ Model.transformVerts (scalev s) model | 197 | (case scale of |
197 | Nothing -> return () | 198 | Nothing -> Prelude.id |
198 | setupIO $ toGround model | 199 | Just s -> flip Model.transformVerts $ |
199 | return model | 200 | \(Vec3 x' y' z') -> Vec3 (V3.x s * x') (V3.y s * y') (V3.z s * z')) |
200 | 201 | ||
201 | 202 | (fmap transform $ Model.loadModel file) >>= setupIO . toGround | |
202 | rotateModel :: Model -> Rotation -> IO () | 203 | |
203 | rotateModel model (Rotation x y z order) = | 204 | |
205 | rotateModel :: Rotation -> Model -> Model | ||
206 | rotateModel (Rotation x y z order) model = | ||
204 | let mat = case order of | 207 | let mat = case order of |
205 | XYZ -> rotZ z * rotY y * rotX x | 208 | XYZ -> rotZ z * rotY y * rotX x |
206 | XZY -> rotY y * rotZ z * rotX x | 209 | XZY -> rotY y * rotZ z * rotX x |
@@ -209,8 +212,14 @@ rotateModel model (Rotation x y z order) = | |||
209 | ZXY -> rotY y * rotX x * rotZ z | 212 | ZXY -> rotY y * rotX x * rotZ z |
210 | ZYX -> rotX x * rotY y * rotZ z | 213 | ZYX -> rotX x * rotY y * rotZ z |
211 | normalMat = fastNormalMatrix mat | 214 | normalMat = fastNormalMatrix mat |
215 | |||
216 | vTransform (Vec3 x' y' z') = | ||
217 | let v = mat `mulp` (vec3 x' y' z') in Vec3 (V3.x v) (V3.y v) (V3.z v) | ||
218 | |||
219 | nTransform (Vec3 x' y' z') = | ||
220 | let v = normalMat `M3.mul` (vec3 x' y' z') in Vec3 (V3.x v) (V3.y v) (V3.z v) | ||
212 | in | 221 | in |
213 | Model.transformVerts mat model >> Model.transformNormals normalMat model | 222 | flip Model.transformVerts vTransform . flip Model.transformNormals nTransform $ model |
214 | 223 | ||
215 | 224 | ||
216 | loadTexture :: FilePath -> Loader GLSL.Texture | 225 | loadTexture :: FilePath -> Loader GLSL.Texture |