aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Sunet <jeannekamikaze@gmail.com>2012-08-10 16:09:17 +0200
committerMarc Sunet <jeannekamikaze@gmail.com>2012-08-10 16:09:17 +0200
commit7404d6f6ca90777cae55bdb352aa85bcc0edf7cc (patch)
tree4649619544898b0434dd01d737050f463a5b51f4
parentcea463d491bde214cb3d7839433c6685ec78679c (diff)
Major rework: Model is now both C and Haskell friendly
-rw-r--r--Spear.lkshs12
-rw-r--r--Spear.lkshw2
-rw-r--r--Spear/Assets/Model.hsc378
-rw-r--r--Spear/Assets/Model/Model.c56
-rw-r--r--Spear/Assets/Model/Model.h6
-rw-r--r--Spear/Render/Model.hsc4
-rw-r--r--Spear/Scene/Loader.hs37
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 @@
1Version of session file format: 1Version of session file format:
2 1 2 1
3Time of storage: 3Time of storage:
4 "Thu Aug 9 13:31:29 CEST 2012" 4 "Fri Aug 10 15:19:04 CEST 2012"
5Layout: 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 5Layout: 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
6Population: [(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])] 6Population: [(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])]
7Window size: (1841,964) 7Window size: (1841,964)
8Completion size: 8Completion size:
9 (750,400) 9 (750,400)
10Workspace: Just "/home/jeanne/programming/haskell/Spear/Spear.lkshw" 10Workspace: Just "/home/jeanne/programming/haskell/Spear/Spear.lkshw"
11Active pane: Just "World.hs" 11Active pane: Just "Model.hsc"
12Toolbar visible: 12Toolbar visible:
13 True 13 True
14FindbarState: (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}) 14FindbarState: (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})
15Recently opened files: 15Recently 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"]
17Recently opened workspaces: 17Recently 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 @@
1Version of workspace file format: 1Version of workspace file format:
2 1 2 1
3Time of storage: 3Time of storage:
4 "Wed Aug 8 21:04:06 CEST 2012" 4 "Fri Aug 10 15:56:20 CEST 2012"
5Name of the workspace: 5Name of the workspace:
6 "Spear" 6 "Spear"
7File paths of contained packages: 7File 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 @@
3module Spear.Assets.Model 3module 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
36import Spear.Setup 28import Spear.Setup
37import qualified Spear.Math.Matrix4 as M4
38import qualified Spear.Math.Matrix3 as M3
39import Spear.Math.MatrixUtils
40 29
41 30
42import qualified Data.ByteString.Char8 as B 31import qualified Data.ByteString.Char8 as B
43import Data.Char (toLower) 32import Data.Char (toLower)
44import Data.List (splitAt, elemIndex) 33import Data.List (splitAt, elemIndex)
45import qualified Data.Vector as V 34import qualified Data.Vector.Storable as V
46import Foreign.Ptr 35import Foreign.Ptr
47import Foreign.Storable 36import Foreign.Storable
48import Foreign.C.Types 37import Foreign.C.Types
@@ -69,10 +58,11 @@ data ModelErrorCode
69 58
70 59
71sizeFloat = #{size float} 60sizeFloat = #{size float}
61sizePtr = #{size int*}
72 62
73 63
74-- | A 3D vector. 64-- | A 3D vector.
75data Vec3 = Vec3 !CFloat !CFloat !CFloat 65data Vec3 = Vec3 !Float !Float !Float
76 66
77 67
78instance Storable Vec3 where 68instance 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.
95data TexCoord = TexCoord !CFloat !CFloat 85data TexCoord = TexCoord !Float !Float
96 86
97 87
98instance Storable TexCoord where 88instance 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
112data CTriangle = CTriangle !CUShort !CUShort !CUShort !CUShort !CUShort !CUShort 102-- | A raw triangle holding vertex/normal and texture indices.
103data 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
115data Skin = Skin !(Ptr Char) 113instance 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
118data CAnimation = CAnimation !B.ByteString !CUInt !CUInt 138-- | A model skin.
139newtype Skin = Skin { skinName :: B.ByteString }
119 140
120 141
121-- | The model's underlying representation. 142instance Storable Skin where
122data 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
138instance Storable CModel where 154-- | A model animation.
139 sizeOf _ = #{size Model} 155--
140 alignment _ = alignment (undefined :: CUInt) 156-- See also: 'animation', 'animationByName', 'numAnimations'.
157data 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 164instance 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
177instance 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-- 181data Model = Model
195-- See also: 'animation', 'animationByName', 'numAnimations'. 182 { vertices :: V.Vector Vec3 -- ^ Array of 'numFrames' * 'numVerts' vertices.
196data 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
197instance 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''.
203data Triangle = Triangle 250data 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'.
245data Model = Model
246 { modelData :: CModel
247 , mAnimations :: V.Vector Animation
248 , rkey :: Resource
249 }
250
251
252foreign import ccall "Model.h model_free" 291foreign import ccall "Model.h model_free"
253 model_free :: Ptr CModel -> IO () 292 model_free :: Ptr Model -> IO ()
254 293
255 294
256foreign import ccall "MD2_load.h MD2_load" 295foreign 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
260foreign import ccall "OBJ_load.h OBJ_load" 299foreign 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
264md2_load :: Ptr CChar -> CChar -> CChar -> Ptr CModel -> IO ModelErrorCode 303md2_load :: Ptr CChar -> CChar -> CChar -> Ptr Model -> IO ModelErrorCode
265md2_load file clockwise leftHanded model = 304md2_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
269obj_load :: Ptr CChar -> CChar -> CChar -> Ptr CModel -> IO ModelErrorCode 308obj_load :: Ptr CChar -> CChar -> CChar -> Ptr Model -> IO ModelErrorCode
270obj_load file clockwise leftHanded model = 309obj_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.
275loadModel :: FilePath -> Setup Model 314loadModel :: FilePath -> Setup Model
276loadModel file = do 315loadModel 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
312fromCAnimation :: CAnimation -> Animation
313fromCAnimation (CAnimation cname start end) =
314 Animation (B.unpack cname) (fromIntegral start) (fromIntegral end)
315
316
317-- | Release the model.
318releaseModel :: Model -> Setup ()
319releaseModel = release . rkey
320
321
322-- | Free the C model.
323freeModel :: CModel -> IO ()
324freeModel 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
329animated = (>1) . numFrames 347animated = (>1) . numFrames
330 348
331 349
332-- | Return the model's number of frames.
333numFrames :: Model -> Int
334numFrames = fromIntegral . cnFrames . modelData
335
336
337-- | Return the model's number of vertices.
338numVertices :: Model -> Int
339numVertices = fromIntegral . cnVerts . modelData
340
341
342-- | Return the model's number of triangles.
343numTriangles :: Model -> Int
344numTriangles = fromIntegral . cnTris . modelData
345
346
347-- | Return the model's number of texture coordinates.
348numTexCoords :: Model -> Int
349numTexCoords = fromIntegral . cnTexCoords . modelData
350
351
352-- | Return the model's number of skins.
353numSkins :: Model -> Int
354numSkins = fromIntegral . cnSkins . modelData
355
356
357-- | Return the underlying C model.
358cmodel :: Model -> CModel
359cmodel = modelData
360
361
362-- | Return the model's ith animation. 350-- | Return the model's ith animation.
363animation :: Model -> Int -> Animation 351animation :: Model -> Int -> Animation
364animation model i = mAnimations model V.! i 352animation 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.
368animationByName :: Model -> String -> Maybe Animation 356animationByName :: Model -> String -> Maybe Animation
369animationByName model anim = V.find ((==) anim . name) $ mAnimations model 357animationByName 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.
373numAnimations :: Model -> Int
374numAnimations = 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.
378triangles :: Model -> IO [Triangle] 362triangles' :: Model -> IO [Triangle]
379triangles m@(Model model _ _) = 363triangles' 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
388foreign import ccall "Model.h model_copy_triangles" 372foreign 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.
393transformVerts :: M4.Matrix4 -> Model -> IO ()
394transformVerts 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.
402transformNormals :: M3.Matrix3 -> Model -> IO ()
403transformNormals 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
410foreign import ccall "Model.h model_transform_vertices" 376-- | Transform the model's vertices.
411 model_transform_vertices :: Ptr CModel -> Ptr M4.Matrix4 -> IO () 377transformVerts :: Model -> (Vec3 -> Vec3) -> Model
378transformVerts 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
414foreign import ccall "Model.h model_transform_normals" 385-- | Transform the model's normals.
415 model_transform_normals :: Ptr CModel -> Ptr M3.Matrix3 -> IO () 386transformNormals :: Model -> (Vec3 -> Vec3) -> Model
387transformNormals 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.
419toGround :: Model -> IO () 395toGround :: Model -> IO Model
420toGround (Model model _ _) = with model model_to_ground 396toGround 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
423foreign import ccall "Model.h model_to_ground" 403foreign 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
30static 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
41static 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
60void 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
73void 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
86void model_to_ground (Model* model) 30void 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.
85void model_free (Model* model); 85void model_free (Model* model);
86 86
87/// Transform the Model's vertices by the given matrix.
88void model_transform_verts (Model* model, float mat[16]);
89
90/// Transform the Model's normals by the given matrix.
91void 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.
94void model_to_ground (Model* model); 88void 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
53foreign import ccall "RenderModel.h render_model_from_model_asset" 53foreign 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.
58renderModelFromModel :: Assets.Model -> IO RenderModel 58renderModelFromModel :: Assets.Model -> IO RenderModel
59renderModelFromModel m = with (Assets.cmodel m) $ \mPtr -> alloca $ \mdPtr -> do 59renderModelFromModel 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
20import Spear.Assets.Model as Model 20import Spear.Assets.Model as Model
21import qualified Spear.GLSL as GLSL 21import qualified Spear.GLSL as GLSL
22import qualified Spear.Math.Matrix3 as M3
22import Spear.Math.Matrix4 as M4 23import Spear.Math.Matrix4 as M4
23import Spear.Math.MatrixUtils (fastNormalMatrix) 24import Spear.Math.MatrixUtils (fastNormalMatrix)
24import Spear.Math.Vector3 as V3 25import Spear.Math.Vector3 as V3
@@ -188,19 +189,21 @@ newModel (SceneLeaf _ props) = do
188 189
189loadModel' :: FilePath -> Maybe Rotation -> Maybe Vector3 -> Setup Model 190loadModel' :: FilePath -> Maybe Rotation -> Maybe Vector3 -> Setup Model
190loadModel' file rotation scale = do 191loadModel' 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
202rotateModel :: Model -> Rotation -> IO () 203
203rotateModel model (Rotation x y z order) = 204
205rotateModel :: Rotation -> Model -> Model
206rotateModel (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
216loadTexture :: FilePath -> Loader GLSL.Texture 225loadTexture :: FilePath -> Loader GLSL.Texture