diff options
-rw-r--r-- | Spear/Assets/Model.hsc | 146 | ||||
-rw-r--r-- | Spear/Assets/Model/Model.c | 28 | ||||
-rw-r--r-- | Spear/Assets/Model/Model.h | 20 |
3 files changed, 154 insertions, 40 deletions
diff --git a/Spear/Assets/Model.hsc b/Spear/Assets/Model.hsc index 9e718c7..cb0ef3f 100644 --- a/Spear/Assets/Model.hsc +++ b/Spear/Assets/Model.hsc | |||
@@ -4,21 +4,17 @@ module Spear.Assets.Model | |||
4 | ( | 4 | ( |
5 | -- * Data types | 5 | -- * Data types |
6 | ModelErrorCode | 6 | ModelErrorCode |
7 | , Vec3 | 7 | , Vec3(..) |
8 | , TexCoord | 8 | , TexCoord(..) |
9 | , CModel(..) | 9 | , CModel |
10 | , Animation(..) | 10 | , Animation(..) |
11 | , Triangle(..) | ||
11 | , Model | 12 | , Model |
12 | -- * Loading and unloading | 13 | -- * Loading and unloading |
13 | , loadModel | 14 | , loadModel |
14 | , releaseModel | 15 | , releaseModel |
15 | -- * Accessors | 16 | -- * Accessors |
16 | , animated | 17 | , animated |
17 | , vertices | ||
18 | , normals | ||
19 | , texCoords | ||
20 | , triangles | ||
21 | , skins | ||
22 | , numFrames | 18 | , numFrames |
23 | , numVertices | 19 | , numVertices |
24 | , numTriangles | 20 | , numTriangles |
@@ -28,6 +24,7 @@ module Spear.Assets.Model | |||
28 | , animation | 24 | , animation |
29 | , animationByName | 25 | , animationByName |
30 | , numAnimations | 26 | , numAnimations |
27 | , triangles | ||
31 | -- * Manipulation | 28 | -- * Manipulation |
32 | , transformVerts | 29 | , transformVerts |
33 | , transformNormals | 30 | , transformNormals |
@@ -41,6 +38,7 @@ import qualified Spear.Math.Matrix4 as M4 | |||
41 | import qualified Spear.Math.Matrix3 as M3 | 38 | import qualified Spear.Math.Matrix3 as M3 |
42 | import Spear.Math.MatrixUtils | 39 | import Spear.Math.MatrixUtils |
43 | 40 | ||
41 | |||
44 | import qualified Data.ByteString.Char8 as B | 42 | import qualified Data.ByteString.Char8 as B |
45 | import Data.Char (toLower) | 43 | import Data.Char (toLower) |
46 | import Data.List (splitAt, elemIndex) | 44 | import Data.List (splitAt, elemIndex) |
@@ -51,7 +49,7 @@ import Foreign.C.Types | |||
51 | import Foreign.C.String | 49 | import Foreign.C.String |
52 | import Foreign.Marshal.Utils as Foreign (with) | 50 | import Foreign.Marshal.Utils as Foreign (with) |
53 | import Foreign.Marshal.Alloc (alloca, allocaBytes) | 51 | import Foreign.Marshal.Alloc (alloca, allocaBytes) |
54 | import Foreign.Marshal.Array (copyArray, peekArray) | 52 | import Foreign.Marshal.Array (allocaArray, copyArray, peekArray) |
55 | import Unsafe.Coerce (unsafeCoerce) | 53 | import Unsafe.Coerce (unsafeCoerce) |
56 | 54 | ||
57 | 55 | ||
@@ -70,14 +68,53 @@ data ModelErrorCode | |||
70 | deriving (Eq, Enum, Show) | 68 | deriving (Eq, Enum, Show) |
71 | 69 | ||
72 | 70 | ||
71 | sizeFloat = #{size float} | ||
72 | |||
73 | |||
74 | -- | A 3D vector. | ||
73 | data Vec3 = Vec3 !CFloat !CFloat !CFloat | 75 | data Vec3 = Vec3 !CFloat !CFloat !CFloat |
74 | 76 | ||
77 | |||
78 | instance Storable Vec3 where | ||
79 | sizeOf _ = 3*sizeFloat | ||
80 | alignment _ = alignment (undefined :: CFloat) | ||
81 | |||
82 | peek ptr = do | ||
83 | f0 <- peekByteOff ptr 0 | ||
84 | f1 <- peekByteOff ptr sizeFloat | ||
85 | f2 <- peekByteOff ptr (2*sizeFloat) | ||
86 | return $ Vec3 f0 f1 f2 | ||
87 | |||
88 | poke ptr (Vec3 f0 f1 f2) = do | ||
89 | pokeByteOff ptr 0 f0 | ||
90 | pokeByteOff ptr sizeFloat f1 | ||
91 | pokeByteOff ptr (2*sizeFloat) f2 | ||
92 | |||
93 | |||
94 | -- | A 2D texture coordinate. | ||
75 | data TexCoord = TexCoord !CFloat !CFloat | 95 | data TexCoord = TexCoord !CFloat !CFloat |
76 | 96 | ||
77 | data Triangle = Triangle !CUShort !CUShort !CUShort !CUShort !CUShort !CUShort | 97 | |
98 | instance Storable TexCoord where | ||
99 | sizeOf _ = 2*sizeFloat | ||
100 | alignment _ = alignment (undefined :: CFloat) | ||
101 | |||
102 | peek ptr = do | ||
103 | f0 <- peekByteOff ptr 0 | ||
104 | f1 <- peekByteOff ptr sizeFloat | ||
105 | return $ TexCoord f0 f1 | ||
106 | |||
107 | poke ptr (TexCoord f0 f1) = do | ||
108 | pokeByteOff ptr 0 f0 | ||
109 | pokeByteOff ptr sizeFloat f1 | ||
110 | |||
111 | |||
112 | data CTriangle = CTriangle !CUShort !CUShort !CUShort !CUShort !CUShort !CUShort | ||
113 | |||
78 | 114 | ||
79 | data Skin = Skin !(Ptr Char) | 115 | data Skin = Skin !(Ptr Char) |
80 | 116 | ||
117 | |||
81 | data CAnimation = CAnimation !B.ByteString !CUInt !CUInt | 118 | data CAnimation = CAnimation !B.ByteString !CUInt !CUInt |
82 | 119 | ||
83 | 120 | ||
@@ -86,7 +123,7 @@ data CModel = CModel | |||
86 | { cVerts :: Ptr Vec3 -- ^ Pointer to an array of 'cnFrames' * 'cnVerts' vertices. | 123 | { cVerts :: Ptr Vec3 -- ^ Pointer to an array of 'cnFrames' * 'cnVerts' vertices. |
87 | , cNormals :: Ptr Vec3 -- ^ Pointer to an array of 'cnFrames' * cnVerts normals. | 124 | , cNormals :: Ptr Vec3 -- ^ Pointer to an array of 'cnFrames' * cnVerts normals. |
88 | , cTexCoords :: Ptr TexCoord -- ^ Pointer to an array of 'cnTris' texture coordinates. | 125 | , cTexCoords :: Ptr TexCoord -- ^ Pointer to an array of 'cnTris' texture coordinates. |
89 | , cTris :: Ptr Triangle -- ^ Pointer to an array of 'cnTris' triangles. | 126 | , cTris :: Ptr CTriangle -- ^ Pointer to an array of 'cnTris' triangles. |
90 | , cSkins :: Ptr Skin -- ^ Pointer to an array of 'cnSkins' skins. | 127 | , cSkins :: Ptr Skin -- ^ Pointer to an array of 'cnSkins' skins. |
91 | , cAnimations :: Ptr CAnimation -- ^ Pointer to an array of 'cnAnimations' animations. | 128 | , cAnimations :: Ptr CAnimation -- ^ Pointer to an array of 'cnAnimations' animations. |
92 | , cnFrames :: CUInt -- ^ Number of frames. | 129 | , cnFrames :: CUInt -- ^ Number of frames. |
@@ -153,6 +190,9 @@ instance Storable CAnimation where | |||
153 | #{poke animation, end} ptr end | 190 | #{poke animation, end} ptr end |
154 | 191 | ||
155 | 192 | ||
193 | -- | A model's animation. | ||
194 | -- | ||
195 | -- See also: 'animation', 'animationByName', 'numAnimations'. | ||
156 | data Animation = Animation | 196 | data Animation = Animation |
157 | { name :: String | 197 | { name :: String |
158 | , start :: Int | 198 | , start :: Int |
@@ -160,6 +200,47 @@ data Animation = Animation | |||
160 | } | 200 | } |
161 | 201 | ||
162 | 202 | ||
203 | data Triangle = Triangle | ||
204 | { v0 :: Vec3 | ||
205 | , v1 :: Vec3 | ||
206 | , v2 :: Vec3 | ||
207 | , n0 :: Vec3 | ||
208 | , n1 :: Vec3 | ||
209 | , n2 :: Vec3 | ||
210 | , t0 :: TexCoord | ||
211 | , t1 :: TexCoord | ||
212 | , t2 :: TexCoord | ||
213 | } | ||
214 | |||
215 | |||
216 | instance Storable Triangle where | ||
217 | sizeOf _ = #{size model_triangle} | ||
218 | alignment _ = alignment (undefined :: Float) | ||
219 | |||
220 | peek ptr = do | ||
221 | v0 <- #{peek model_triangle, v0} ptr | ||
222 | v1 <- #{peek model_triangle, v1} ptr | ||
223 | v2 <- #{peek model_triangle, v2} ptr | ||
224 | n0 <- #{peek model_triangle, n0} ptr | ||
225 | n1 <- #{peek model_triangle, n1} ptr | ||
226 | n2 <- #{peek model_triangle, n2} ptr | ||
227 | t0 <- #{peek model_triangle, t0} ptr | ||
228 | t1 <- #{peek model_triangle, t1} ptr | ||
229 | t2 <- #{peek model_triangle, t2} ptr | ||
230 | return $ Triangle v0 v1 v2 n0 n1 n2 t0 t1 t2 | ||
231 | |||
232 | poke ptr (Triangle v0 v1 v2 n0 n1 n2 t0 t1 t2) = do | ||
233 | #{poke model_triangle, v0} ptr v0 | ||
234 | #{poke model_triangle, v1} ptr v1 | ||
235 | #{poke model_triangle, v2} ptr v2 | ||
236 | #{poke model_triangle, n0} ptr n0 | ||
237 | #{poke model_triangle, n1} ptr n1 | ||
238 | #{poke model_triangle, n2} ptr n2 | ||
239 | #{poke model_triangle, t0} ptr t0 | ||
240 | #{poke model_triangle, t1} ptr t1 | ||
241 | #{poke model_triangle, t2} ptr t2 | ||
242 | |||
243 | |||
163 | -- | A model 'Resource'. | 244 | -- | A model 'Resource'. |
164 | data Model = Model | 245 | data Model = Model |
165 | { modelData :: CModel | 246 | { modelData :: CModel |
@@ -248,31 +329,6 @@ animated :: Model -> Bool | |||
248 | animated = (>1) . numFrames | 329 | animated = (>1) . numFrames |
249 | 330 | ||
250 | 331 | ||
251 | -- | Return the model's vertices. | ||
252 | vertices :: Model -> Ptr Vec3 | ||
253 | vertices = cVerts . modelData | ||
254 | |||
255 | |||
256 | -- | Return the model's normals. | ||
257 | normals :: Model -> Ptr Vec3 | ||
258 | normals = cNormals . modelData | ||
259 | |||
260 | |||
261 | -- | Return the model's texCoords. | ||
262 | texCoords :: Model -> Ptr TexCoord | ||
263 | texCoords = cTexCoords . modelData | ||
264 | |||
265 | |||
266 | -- | Return the model's triangles. | ||
267 | triangles :: Model -> Ptr Triangle | ||
268 | triangles = cTris . modelData | ||
269 | |||
270 | |||
271 | -- | Return the model's skins. | ||
272 | skins :: Model -> Ptr Skin | ||
273 | skins = cSkins . modelData | ||
274 | |||
275 | |||
276 | -- | Return the model's number of frames. | 332 | -- | Return the model's number of frames. |
277 | numFrames :: Model -> Int | 333 | numFrames :: Model -> Int |
278 | numFrames = fromIntegral . cnFrames . modelData | 334 | numFrames = fromIntegral . cnFrames . modelData |
@@ -318,6 +374,21 @@ numAnimations :: Model -> Int | |||
318 | numAnimations = V.length . mAnimations | 374 | numAnimations = V.length . mAnimations |
319 | 375 | ||
320 | 376 | ||
377 | -- | Return a copy of the model's triangles. | ||
378 | triangles :: Model -> IO [Triangle] | ||
379 | triangles m@(Model model _ _) = | ||
380 | let n = numVertices m * numFrames m | ||
381 | in with model $ \modelPtr -> | ||
382 | allocaArray n $ \arrayPtr -> do | ||
383 | model_copy_triangles modelPtr arrayPtr | ||
384 | tris <- peekArray n arrayPtr | ||
385 | return tris | ||
386 | |||
387 | |||
388 | foreign import ccall "Model.h model_copy_triangles" | ||
389 | model_copy_triangles :: Ptr CModel -> Ptr Triangle -> IO () | ||
390 | |||
391 | |||
321 | -- | Transform the model's vertices with the given matrix. | 392 | -- | Transform the model's vertices with the given matrix. |
322 | transformVerts :: M4.Matrix4 -> Model -> IO () | 393 | transformVerts :: M4.Matrix4 -> Model -> IO () |
323 | transformVerts mat (Model model _ _) = | 394 | transformVerts mat (Model model _ _) = |
@@ -351,6 +422,3 @@ toGround (Model model _ _) = with model model_to_ground | |||
351 | 422 | ||
352 | foreign import ccall "Model.h model_to_ground" | 423 | foreign import ccall "Model.h model_to_ground" |
353 | model_to_ground :: Ptr CModel -> IO () | 424 | model_to_ground :: Ptr CModel -> IO () |
354 | |||
355 | |||
356 | sizeFloat = #{size float} | ||
diff --git a/Spear/Assets/Model/Model.c b/Spear/Assets/Model/Model.c index f6b2f1f..a682991 100644 --- a/Spear/Assets/Model/Model.c +++ b/Spear/Assets/Model/Model.c | |||
@@ -106,3 +106,31 @@ void model_to_ground (Model* model) | |||
106 | } | 106 | } |
107 | } | 107 | } |
108 | } | 108 | } |
109 | |||
110 | |||
111 | void model_copy_triangles (Model* model, unsigned frame, model_triangle* tris) | ||
112 | { | ||
113 | int i; | ||
114 | int j = model->numVertices; | ||
115 | |||
116 | vec3* v = model->vertices + j * frame; | ||
117 | vec3* n = model->normals + j * frame; | ||
118 | texCoord* t = model->texCoords; | ||
119 | triangle* tri = model->triangles; | ||
120 | |||
121 | |||
122 | for (i = 0; i < j; ++i, ++tri, ++tris) | ||
123 | { | ||
124 | tris->v0 = v[tri->vertexIndices[0]]; | ||
125 | tris->v1 = v[tri->vertexIndices[1]]; | ||
126 | tris->v2 = v[tri->vertexIndices[2]]; | ||
127 | |||
128 | tris->n0 = n[tri->vertexIndices[0]]; | ||
129 | tris->n1 = n[tri->vertexIndices[1]]; | ||
130 | tris->n2 = n[tri->vertexIndices[2]]; | ||
131 | |||
132 | tris->t0 = t[tri->textureIndices[0]]; | ||
133 | tris->t1 = t[tri->textureIndices[1]]; | ||
134 | tris->t2 = t[tri->textureIndices[2]]; | ||
135 | } | ||
136 | } | ||
diff --git a/Spear/Assets/Model/Model.h b/Spear/Assets/Model/Model.h index 84be6aa..275b040 100644 --- a/Spear/Assets/Model/Model.h +++ b/Spear/Assets/Model/Model.h | |||
@@ -49,7 +49,7 @@ typedef struct | |||
49 | texCoord* texCoords; // One array for all frames. | 49 | texCoord* texCoords; // One array for all frames. |
50 | triangle* triangles; // One array for all frames. | 50 | triangle* triangles; // One array for all frames. |
51 | skin* skins; // Holds the model's texture files. | 51 | skin* skins; // Holds the model's texture files. |
52 | animation* animations; // Holds the model's animations. | 52 | animation* animations; // Holds the model's animations. |
53 | 53 | ||
54 | unsigned int numFrames; | 54 | unsigned int numFrames; |
55 | unsigned int numVertices; // Number of vertices per frame. | 55 | unsigned int numVertices; // Number of vertices per frame. |
@@ -61,6 +61,21 @@ typedef struct | |||
61 | Model; | 61 | Model; |
62 | 62 | ||
63 | 63 | ||
64 | typedef struct | ||
65 | { | ||
66 | vec3 v0; | ||
67 | vec3 v1; | ||
68 | vec3 v2; | ||
69 | vec3 n0; | ||
70 | vec3 n1; | ||
71 | vec3 n2; | ||
72 | texCoord t0; | ||
73 | texCoord t1; | ||
74 | texCoord t2; | ||
75 | } | ||
76 | model_triangle; | ||
77 | |||
78 | |||
64 | #ifdef __cplusplus | 79 | #ifdef __cplusplus |
65 | extern "C" { | 80 | extern "C" { |
66 | #endif | 81 | #endif |
@@ -78,6 +93,9 @@ void model_transform_normals (Model* model, float normal[9]); | |||
78 | /// Translate the Model such that its lowest point has y = 0. | 93 | /// Translate the Model such that its lowest point has y = 0. |
79 | void model_to_ground (Model* model); | 94 | void model_to_ground (Model* model); |
80 | 95 | ||
96 | /// Copy the triangles of the given frame from the Model into the given array. | ||
97 | void model_copy_triangles (Model* model, unsigned frame, model_triangle* tris); | ||
98 | |||
81 | #ifdef __cplusplus | 99 | #ifdef __cplusplus |
82 | } | 100 | } |
83 | #endif | 101 | #endif |