Mirai's Miscellaneous Misadventures
M24 / core / animations.c
1
2
3
4#include <mimimi/models.h>
5#include <mimimi/appearances.h>
6#include <mimimi/allocators.h>
7#include <mimimi/animations.h>
8#include <mimimi/assets.h>
9#include <mimimi/poses.h>
10
11#include "math.c"
12
13static unsigned char mimimi_layer_pixel(struct mimimi_layer *layer, unsigned char y_angle, int x, int y)
14{
15 int h = layer->count;
16
17 if (y < 0) return 0;
18 if (y >= h) return 0;
19
20 int w0 = layer->rows[y].width;
21 int w1 = layer->rows[y].height;
22
23 int w = mimimi_sine[y_angle] * w0 + (128 - mimimi_sine[y_angle]) * w1;
24 w /= 128;
25
26 if (x < -w / 2) return 0;
27 if (x >= w / 2) return 0;
28
29 x += w / 2;
30
31 int count = layer->rows[y].count;
32
33 int a = y_angle;
34 a *= count;
35 a += 128;
36 a /= 256;
37 a += x;
38 a %= count;
39
40 return layer->rows[y].colors[a];
41}
42
43static void mimimi_swap(int *x, int *y)
44{
45 int z = *x;
46 *x = *y;
47 *y = z;
48}
49
50static void mimimi_layer(struct mimimi_image *image, struct mimimi_layer *layer, int x0, int y0, struct mimimi_pose_layer *pose_layer, int behind)
51{
52 int width = image->width;
53 int height = image->height;
54
55 unsigned char y_angle = pose_layer->y_angle;
56 int z_angle = mimimi_mod(pose_layer->z_angle, 4);
57
58 if (behind != 0) y_angle += 128;
59
60 if (z_angle == 0)
61 {
62 for (int y = 0 ; y < height ; y++)
63 for (int x = 0 ; x < width ; x++)
64 {
65 int x1 = x + layer->x - x0;
66 int y1 = y + layer->y - y0;
67
68 x1 += pose_layer->slant * (y - y0) / 256;
69
70 if (behind != 0) x1 = -x1 - 1;
71
72 unsigned char color = mimimi_layer_pixel(layer, y_angle, x1, y1);
73 if (color != 0) image->colors[x + y * width] = color;
74 }
75 }
76
77 if (z_angle == 1)
78 {
79 for (int y = 0 ; y < height ; y++)
80 for (int x = 0 ; x < width ; x++)
81 {
82 int x1 = x - layer->y - x0;
83 int y1 = y + layer->x - y0;
84
85 y1 -= pose_layer->slant * (x - x0) / 256;
86
87 if (behind != 0) y1 = -y1 - 1;
88
89 unsigned char color = mimimi_layer_pixel(layer, y_angle, y1, -x1);
90 if (color != 0) image->colors[x + y * width] = color;
91 }
92
93 return;
94 }
95
96 if (z_angle == 2)
97 {
98 for (int y = 0 ; y < height ; y++)
99 for (int x = 0 ; x < width ; x++)
100 {
101 int x1 = x - layer->x - x0;
102 int y1 = y - layer->y - y0;
103
104 x1 += pose_layer->slant * (y - y0) / 256;
105
106 if (behind != 0) x1 = -x1 + 1;
107
108 unsigned char color = mimimi_layer_pixel(layer, y_angle, -x1, -y1);
109 if (color != 0) image->colors[x + y * width] = color;
110 }
111
112 return;
113 }
114
115 if (z_angle == 3)
116 {
117 for (int y = 0 ; y < height ; y++)
118 for (int x = 0 ; x < width ; x++)
119 {
120 int x1 = x + layer->y - x0;
121 int y1 = y - layer->x - y0;
122
123 y1 -= pose_layer->slant * (x - x0) / 256;
124
125 if (behind != 0) y1 = -y1 + 1;
126
127 unsigned char color = mimimi_layer_pixel(layer, y_angle, -y1, x1);
128 if (color != 0) image->colors[x + y * width] = color;
129 }
130
131 return;
132 }
133}
134
135static void mimimi_apply_y_angle(struct mimimi_model *model, struct mimimi_layer *layers, struct mimimi_pose_layer *pose_layers)
136{
137 for (int i = 0 ; i < model->count ; i++)
138 {
139 struct mimimi_layer *layer = layers + i;
140 struct mimimi_pose_layer *pose_layer = pose_layers + i;
141 int parent_index = model->layers[i].parent_index;
142
143 if (i == parent_index) continue;
144
145 int parent_y_angle = pose_layers[parent_index].y_angle;
146 pose_layer->y_angle += parent_y_angle;
147
148 unsigned char y_angle = parent_y_angle;
149
150 int sin = mimimi_sine[y_angle];
151 int cos = mimimi_cosine[y_angle];
152
153 int x = layer->x;
154 int z = layer->z;
155
156 layer->x = cos*x / 128 + sin*z / 128;
157 layer->z = cos*z / 128 - sin*x / 128;
158 }
159}
160
161static void mimimi_apply_z_angle(struct mimimi_model *model, struct mimimi_layer *layers, struct mimimi_pose_layer *pose_layers, struct mimimi_allocator *allocator)
162{
163 int *xs = (*allocator->allocate)(sizeof *xs * model->count);
164 int *ys = (*allocator->allocate)(sizeof *ys * model->count);
165
166 for (int i = 0 ; i < model->count ; i++)
167 {
168 struct mimimi_layer *layer = layers + i;
169 struct mimimi_pose_layer *pose_layer = pose_layers + i;
170 int parent_index = model->layers[i].parent_index;
171
172 xs[i] = layer->x;
173 ys[i] = layer->y;
174 if (i == parent_index) continue;
175 xs[i] += xs[parent_index];
176 ys[i] += ys[parent_index];
177
178 int z_angle = mimimi_mod(pose_layer->z_angle, 4);
179
180 int x = xs[i];
181 int y = ys[i];
182 if (z_angle == 1) x = -x, mimimi_swap(&x, &y);
183 if (z_angle == 2) x = -x, y = -y;
184 if (z_angle == 3) y = -y, mimimi_swap(&x, &y);
185 layer->x = x - xs[parent_index];
186 layer->y = y - ys[parent_index];
187
188 if (z_angle == 1) xs[i] = -xs[i], mimimi_swap(xs + i, ys + i);
189 if (z_angle == 2) xs[i] = -xs[i], ys[i] = -ys[i];
190 if (z_angle == 3) ys[i] = -ys[i], mimimi_swap(xs + i, ys + i);
191 }
192
193 (*allocator->deallocate)(xs);
194 (*allocator->deallocate)(ys);
195}
196
197static void mimimi_apply_slant(struct mimimi_model *model, struct mimimi_layer *layers, struct mimimi_pose_layer *pose_layers, struct mimimi_allocator *allocator)
198{
199 int *ys = (*allocator->allocate)(sizeof *ys * model->count);
200
201 for (int i = 0 ; i < model->count ; i++)
202 {
203 struct mimimi_layer *layer = layers + i;
204 struct mimimi_pose_layer *pose_layer = pose_layers + i;
205 int parent_index = model->layers[i].parent_index;
206
207 ys[i] = layer->y;
208 if (i == parent_index) continue;
209 ys[i] += ys[parent_index];
210
211 int y = ys[i];
212 layer->x += pose_layer->slant * ys[i] / 256;
213 }
214
215 (*allocator->deallocate)(ys);
216}
217
218static void mimimi_absolutize(struct mimimi_model *model, struct mimimi_layer *layers, struct mimimi_pose_layer *pose_layers)
219{
220 for (int i = 0 ; i < model->count ; i++)
221 {
222 struct mimimi_layer *layer = layers + i;
223 struct mimimi_pose_layer *pose_layer = pose_layers + i;
224 int parent_index = model->layers[i].parent_index;
225 if (i == parent_index) continue;
226
227 layer->x += layers[parent_index].x;
228 layer->y += layers[parent_index].y;
229 layer->z += layers[parent_index].z;
230
231 pose_layer->slant += pose_layers[parent_index].slant;
232 pose_layer->z_angle += pose_layers[parent_index].z_angle;
233 pose_layer->z_angle = mimimi_mod(pose_layer->z_angle, 4);
234 }
235}
236
237void mimimi_pose(struct mimimi_image *image, struct mimimi_model *model, struct mimimi_pose *pose, struct mimimi_allocator *allocator)
238{
239 struct mimimi_layer *layers = (*allocator->allocate)(sizeof *layers * model->count);
240 struct mimimi_pose_layer *pose_layers = (*allocator->allocate)(sizeof *pose_layers * model->count);
241
242 struct mimimi_half_layer { int behind; int z; struct mimimi_layer *layer; struct mimimi_pose_layer *pose_layer; } *half_layers = (*allocator->allocate)(sizeof *half_layers * model->count * 2);
243
244 for (int i = 0 ; i < model->count ; i++)
245 {
246 int parent_index = model->layers[i].parent_index;
247
248 struct mimimi_layer *layer = layers + i;
249 *layer = *model->layers[i].layer;
250
251 struct mimimi_pose_layer *pose_layer = pose_layers + i;
252
253 if (i < pose->count)
254 {
255 *pose_layer = pose->layers[i];
256 }
257 else
258 {
259 pose_layer->slant = 0;
260 pose_layer->y_angle = 0;
261 pose_layer->z_angle = 0;
262 }
263 }
264
265 mimimi_apply_y_angle(model, layers, pose_layers);
266 mimimi_apply_z_angle(model, layers, pose_layers, allocator);
267 mimimi_apply_slant(model, layers, pose_layers, allocator);
268 mimimi_absolutize(model, layers, pose_layers);
269
270 for (int i = 0 ; i < model->count ; i++)
271 {
272 struct mimimi_layer *layer = layers + i;
273 struct mimimi_pose_layer *pose_layer = pose_layers + i;
274
275 unsigned char y_angle = pose_layers[i].y_angle;
276
277 int width = layer->width;
278
279 half_layers[i * 2 + 0].behind = 0;
280 half_layers[i * 2 + 0].z = layer->z + width;
281 half_layers[i * 2 + 0].layer = layer;
282 half_layers[i * 2 + 0].pose_layer = pose_layer;
283
284 half_layers[i * 2 + 1].behind = 1;
285 half_layers[i * 2 + 1].z = layer->z - width;
286 half_layers[i * 2 + 1].layer = layer;
287 half_layers[i * 2 + 1].pose_layer = pose_layer;
288 }
289
290
291 for (int i = 0 ; i < model->count * 2 ; i++)
292 {
293 int a = half_layers[i].z;
294
295 int k = i;
296 for (int j = i - 1 ; j >= 0 ; j--)
297 {
298 int b = half_layers[j].z;
299 if (a >= b) break;
300
301 struct mimimi_half_layer half_layer = half_layers[k];
302 half_layers[k] = half_layers[j];
303 half_layers[j] = half_layer;
304
305 k = j;
306 }
307 }
308
309 for (int y = 0 ; y < image->height ; y++)
310 for (int x = 0 ; x < image->width ; x++)
311 image->colors[x + y * image->width] = 0;
312
313 for (int i = 0 ; i < model->count * 2 ; i++)
314 {
315 struct mimimi_half_layer *half_layer = half_layers + i;
316 mimimi_layer(image, half_layer->layer, pose->x, pose->y, half_layer->pose_layer, half_layer->behind);
317 }
318
319 (*allocator->deallocate)(layers);
320 (*allocator->deallocate)(pose_layers);
321 (*allocator->deallocate)(half_layers);
322}
323
324static void mimimi_interpolate_pose_layer(struct mimimi_pose_layer *a, struct mimimi_pose_layer *b, int i, int count)
325{
326 int slant = a->slant * (count - i) / count;
327 slant += mimimi_div(b->slant * i, count);
328
329 int y_angle = a->y_angle * (count - i) / count;
330 y_angle += mimimi_div(b->y_angle * i, count);
331
332 int z_angle = a->z_angle * (count - i) / count;
333 z_angle += mimimi_div(b->z_angle * i, count);
334
335 a->slant = slant;
336 a->y_angle = y_angle;
337 a->z_angle = z_angle;
338}
339
340static void mimimi_interpolate_pose(struct mimimi_pose *a, struct mimimi_pose *b, int i, int count)
341{
342 if (count == 0) return;
343
344 int x = a->x * (count - i) / count;
345 x += mimimi_div(b->x * i, count);
346
347 int y = a->y * (count - i) / count;
348 y += mimimi_div(b->y * i, count);
349
350 a->x = x;
351 a->y = y;
352
353 for (int j = 0 ; j < a->count ; j++)
354 mimimi_interpolate_pose_layer(a->layers + j, b->layers + j, i, count);
355}
356
357void mimimi_movement(struct mimimi_animation *animation, struct mimimi_model *model, struct mimimi_movement *movement, struct mimimi_allocator *allocator)
358{
359 if (movement->count == 1)
360 {
361 for (int i = 0 ; i < animation->count ; i++)
362 mimimi_pose(animation->images + i, model, movement->poses, allocator);
363 return;
364 }
365
366 for (int i = 0 ; i < animation->count ; i++)
367 {
368 int j = i * (movement->count - 1) / animation->count;
369 int k = i - j * animation->count / (movement->count - 1);
370
371 struct mimimi_pose pose = movement->poses[j];
372 mimimi_interpolate_pose(&pose, movement->poses + j + 1, k, animation->count / (movement->count - 1));
373 mimimi_pose(animation->images + i, model, &pose, allocator);
374 }
375}
376
377static void mimimi_appearance_animations(struct mimimi_animation_set *animations, struct mimimi_model *model, int x, int y, int coefficient, struct mimimi_allocator *allocator)
378{
379 int count = animations->standing_animation_count;
380 for (int i = 0 ; i < count ; i++)
381 {
382 struct mimimi_pose_layer layers[3][7] = {};
383
384 int slant = -32 * i / count * coefficient;
385 int y_angle = 64 + (12 + 24 * i / count) * coefficient;
386 int arm_slant = 64 * i / count;
387
388 layers[0][0].y_angle = y_angle;
389 layers[0][0].slant = slant;
390 layers[0][1].slant = -slant;
391 layers[0][2].slant = -arm_slant;
392 layers[0][3].slant = arm_slant;
393 layers[0][4].slant = arm_slant;
394 layers[0][5].slant = -arm_slant;
395
396 layers[1][0].y_angle = y_angle;
397 layers[1][0].slant = slant;
398 layers[1][1].slant = -slant;
399 layers[1][2].slant = arm_slant;
400 layers[1][3].slant = -arm_slant;
401 layers[1][4].slant = -arm_slant;
402 layers[1][5].slant = arm_slant;
403
404 layers[2][0].y_angle = y_angle;
405 layers[2][0].slant = slant;
406 layers[2][1].slant = -slant;
407 layers[2][2].slant = -arm_slant;
408 layers[2][3].slant = arm_slant;
409 layers[2][4].slant = arm_slant;
410 layers[2][5].slant = -arm_slant;
411
412 struct mimimi_pose poses[] = {{x, y, 7, layers[0]}, {x, y, 7, layers[1]}, {x, y, 7, layers[2]}};
413 struct mimimi_movement movement = {3, poses};
414 mimimi_movement(animations->standing + i, model, &movement, allocator);
415 }
416
417 struct mimimi_pose_layer falling_layers[7] = {};
418
419 falling_layers[0].z_angle = coefficient;
420 falling_layers[0].y_angle = 64 + 32 * coefficient;
421 falling_layers[2].slant = -64 * coefficient;
422 falling_layers[2].z_angle = coefficient;
423 falling_layers[3].slant = 64 * coefficient;
424 falling_layers[3].z_angle = coefficient;
425 falling_layers[4].slant = 64 * coefficient;
426 falling_layers[5].slant = 64 * coefficient;
427
428 struct mimimi_pose falling_poses[] = {{x - 12 * coefficient, y - 12, 7, falling_layers}};
429 struct mimimi_movement falling_movement = {1, falling_poses};
430 mimimi_movement(animations->falling, model, &falling_movement, allocator);
431
432 struct mimimi_pose_layer knocked_layers[1] = {};
433
434 knocked_layers[0].z_angle = -coefficient;
435 knocked_layers[0].y_angle = 64 + 32 * coefficient;
436
437 struct mimimi_pose knocked_poses[] = {{x - 12 * coefficient, y - 20, 1, falling_layers}};
438 struct mimimi_movement knocked_movement = {1, knocked_poses};
439 mimimi_movement(animations->knocked, model, &knocked_movement, allocator);
440}
441
442void mimimi_appearance(struct mimimi_appearance *appearance, struct mimimi_model *model, int x, int y, struct mimimi_allocator *allocator)
443{
444 mimimi_appearance_animations(&appearance->left, model, x, y, 1, allocator);
445 mimimi_appearance_animations(&appearance->right, model, x, y, -1, allocator);
446}