diff options
Diffstat (limited to 'Spear/Render/RenderModel.c')
-rw-r--r-- | Spear/Render/RenderModel.c | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/Spear/Render/RenderModel.c b/Spear/Render/RenderModel.c new file mode 100644 index 0000000..3d18a4b --- /dev/null +++ b/Spear/Render/RenderModel.c | |||
@@ -0,0 +1,232 @@ | |||
1 | #include "RenderModel.h" | ||
2 | #include <stdlib.h> // free | ||
3 | #include <string.h> // memcpy | ||
4 | #include <stdio.h> | ||
5 | |||
6 | |||
7 | static void safe_free (void* ptr) | ||
8 | { | ||
9 | if (ptr) | ||
10 | { | ||
11 | free (ptr); | ||
12 | ptr = 0; | ||
13 | } | ||
14 | } | ||
15 | |||
16 | |||
17 | /// Populate elements of an animated model to be rendered from | ||
18 | /// start to end in a loop. | ||
19 | /*int populate_elements_animated (Model* model_asset, RenderModel* model) | ||
20 | { | ||
21 | size_t nverts = model_asset->numVertices; | ||
22 | size_t ntriangles = model_asset->numTriangles; | ||
23 | size_t nframes = model_asset->numFrames; | ||
24 | size_t n = nframes * ntriangles * 3; | ||
25 | |||
26 | model->elements = malloc (56 * n); | ||
27 | if (!model->elements) return -1; | ||
28 | |||
29 | // Populate elements. | ||
30 | |||
31 | size_t f, i; | ||
32 | |||
33 | char* elem = (char*) model->elements; | ||
34 | vec3* v1 = model_asset->vertices; | ||
35 | vec3* v2 = v1 + nverts; | ||
36 | vec3* n1 = model_asset->normals; | ||
37 | vec3* n2 = n1 + nverts; | ||
38 | texCoord* tex = model_asset->texCoords; | ||
39 | |||
40 | for (f = 0; f < nframes; ++f) | ||
41 | { | ||
42 | triangle* t = model_asset->triangles; | ||
43 | |||
44 | for (i = 0; i < ntriangles; ++i) | ||
45 | { | ||
46 | *((vec3*) elem) = v1[t->vertexIndices[0]]; | ||
47 | *((vec3*) (elem + 12)) = v2[t->vertexIndices[0]]; | ||
48 | *((vec3*) (elem + 24)) = n1[t->vertexIndices[0]]; | ||
49 | *((vec3*) (elem + 36)) = n2[t->vertexIndices[0]]; | ||
50 | *((texCoord*) (elem + 48)) = tex[t->textureIndices[0]]; | ||
51 | elem += 56; | ||
52 | |||
53 | *((vec3*) elem) = v1[t->vertexIndices[1]]; | ||
54 | *((vec3*) (elem + 12)) = v2[t->vertexIndices[1]]; | ||
55 | *((vec3*) (elem + 24)) = n1[t->vertexIndices[1]]; | ||
56 | *((vec3*) (elem + 36)) = n2[t->vertexIndices[1]]; | ||
57 | *((texCoord*) (elem + 48)) = tex[t->textureIndices[1]]; | ||
58 | elem += 56; | ||
59 | |||
60 | *((vec3*) elem) = v1[t->vertexIndices[2]]; | ||
61 | *((vec3*) (elem + 12)) = v2[t->vertexIndices[2]]; | ||
62 | *((vec3*) (elem + 24)) = n1[t->vertexIndices[2]]; | ||
63 | *((vec3*) (elem + 36)) = n2[t->vertexIndices[2]]; | ||
64 | *((texCoord*) (elem + 48)) = tex[t->textureIndices[2]]; | ||
65 | elem += 56; | ||
66 | |||
67 | t++; | ||
68 | } | ||
69 | |||
70 | v1 += nverts; | ||
71 | v2 += nverts; | ||
72 | n1 += nverts; | ||
73 | n2 += nverts; | ||
74 | |||
75 | if (f == nframes-2) | ||
76 | { | ||
77 | v2 = model_asset->vertices; | ||
78 | n2 = model_asset->normals; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | return 0; | ||
83 | }*/ | ||
84 | |||
85 | |||
86 | /// Populate elements of an animated model according to its frames | ||
87 | /// of animation. | ||
88 | int populate_elements_animated (Model* model_asset, RenderModel* model) | ||
89 | { | ||
90 | size_t nverts = model_asset->numVertices; | ||
91 | size_t ntriangles = model_asset->numTriangles; | ||
92 | size_t nframes = model_asset->numFrames; | ||
93 | size_t n = nframes * ntriangles * 3; | ||
94 | |||
95 | model->elements = malloc (56 * n); | ||
96 | if (!model->elements) return -1; | ||
97 | |||
98 | // Populate elements. | ||
99 | |||
100 | unsigned f, i, j, u; | ||
101 | |||
102 | char* elem = (char*) model->elements; | ||
103 | animation* anim = model_asset->animations; | ||
104 | |||
105 | for (i = 0; i < model_asset->numAnimations; ++i, anim++) | ||
106 | { | ||
107 | unsigned start = anim->start; | ||
108 | unsigned end = anim->end; | ||
109 | |||
110 | char singleFrameAnim = start == end; | ||
111 | |||
112 | vec3* v1 = model_asset->vertices + start*nverts; | ||
113 | vec3* v2 = singleFrameAnim ? v1 : v1 + nverts; | ||
114 | vec3* n1 = model_asset->normals + start*nverts; | ||
115 | vec3* n2 = singleFrameAnim ? n1 : n1 + nverts; | ||
116 | texCoord* tex = model_asset->texCoords; | ||
117 | |||
118 | for (u = start; u <= end; ++u) | ||
119 | { | ||
120 | triangle* t = model_asset->triangles; | ||
121 | |||
122 | for (j = 0; j < ntriangles; ++j, t++) | ||
123 | { | ||
124 | *((vec3*) elem) = v1[t->vertexIndices[0]]; | ||
125 | *((vec3*) (elem + 12)) = v2[t->vertexIndices[0]]; | ||
126 | *((vec3*) (elem + 24)) = n1[t->vertexIndices[0]]; | ||
127 | *((vec3*) (elem + 36)) = n2[t->vertexIndices[0]]; | ||
128 | *((texCoord*) (elem + 48)) = tex[t->textureIndices[0]]; | ||
129 | elem += 56; | ||
130 | |||
131 | *((vec3*) elem) = v1[t->vertexIndices[1]]; | ||
132 | *((vec3*) (elem + 12)) = v2[t->vertexIndices[1]]; | ||
133 | *((vec3*) (elem + 24)) = n1[t->vertexIndices[1]]; | ||
134 | *((vec3*) (elem + 36)) = n2[t->vertexIndices[1]]; | ||
135 | *((texCoord*) (elem + 48)) = tex[t->textureIndices[1]]; | ||
136 | elem += 56; | ||
137 | |||
138 | *((vec3*) elem) = v1[t->vertexIndices[2]]; | ||
139 | *((vec3*) (elem + 12)) = v2[t->vertexIndices[2]]; | ||
140 | *((vec3*) (elem + 24)) = n1[t->vertexIndices[2]]; | ||
141 | *((vec3*) (elem + 36)) = n2[t->vertexIndices[2]]; | ||
142 | *((texCoord*) (elem + 48)) = tex[t->textureIndices[2]]; | ||
143 | elem += 56; | ||
144 | } | ||
145 | |||
146 | // Advance to the next frame of animation of the current | ||
147 | // animation. | ||
148 | v1 += nverts; | ||
149 | v2 += nverts; | ||
150 | n1 += nverts; | ||
151 | n2 += nverts; | ||
152 | |||
153 | // Reset the secondary pointers to the beginning of the | ||
154 | // animation when we are about to reach the last frame. | ||
155 | if (u == end-1) | ||
156 | { | ||
157 | v2 = model_asset->vertices + start*nverts; | ||
158 | n2 = model_asset->normals + start*nverts; | ||
159 | } | ||
160 | } | ||
161 | } | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | |||
167 | int populate_elements_static (Model* model_asset, RenderModel* model) | ||
168 | { | ||
169 | size_t nverts = model_asset->numVertices; | ||
170 | size_t ntriangles = model_asset->numTriangles; | ||
171 | size_t n = ntriangles * 3; | ||
172 | |||
173 | model->elements = malloc (32 * n); | ||
174 | if (!model->elements) return -1; | ||
175 | |||
176 | // Populate elements. | ||
177 | |||
178 | size_t f, i; | ||
179 | |||
180 | char* elem = (char*) model->elements; | ||
181 | vec3* vert = model_asset->vertices; | ||
182 | vec3* norm = model_asset->normals; | ||
183 | texCoord* tex = model_asset->texCoords; | ||
184 | |||
185 | triangle* t = model_asset->triangles; | ||
186 | |||
187 | for (i = 0; i < ntriangles; ++i) | ||
188 | { | ||
189 | *((vec3*) elem) = vert[t->vertexIndices[0]]; | ||
190 | *((vec3*) (elem + 12)) = norm[t->vertexIndices[0]]; | ||
191 | *((texCoord*) (elem + 24)) = tex[t->textureIndices[0]]; | ||
192 | elem += 32; | ||
193 | |||
194 | *((vec3*) elem) = vert[t->vertexIndices[1]]; | ||
195 | *((vec3*) (elem + 12)) = norm[t->vertexIndices[1]]; | ||
196 | *((texCoord*) (elem + 24)) = tex[t->textureIndices[1]]; | ||
197 | elem += 32; | ||
198 | |||
199 | *((vec3*) elem) = vert[t->vertexIndices[2]]; | ||
200 | *((vec3*) (elem + 12)) = norm[t->vertexIndices[2]]; | ||
201 | *((texCoord*) (elem + 24)) = tex[t->textureIndices[2]]; | ||
202 | elem += 32; | ||
203 | |||
204 | t++; | ||
205 | } | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | |||
211 | int render_model_from_model_asset (Model* model_asset, RenderModel* model) | ||
212 | { | ||
213 | U32 ntriangles = model_asset->numTriangles; | ||
214 | U32 nframes = model_asset->numFrames; | ||
215 | |||
216 | int result; | ||
217 | if (nframes > 1) result = populate_elements_animated (model_asset, model); | ||
218 | else result = populate_elements_static (model_asset, model); | ||
219 | |||
220 | if (result != 0) return result; | ||
221 | |||
222 | model->numFrames = nframes; | ||
223 | model->numVertices = ntriangles * 3; // Number of vertices per frame. | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | |||
229 | void render_model_free (RenderModel* model) | ||
230 | { | ||
231 | safe_free (model->elements); | ||
232 | } | ||