Mirai's Miscellaneous Misadventures
M43 / core / animations.c
1
2
3
4#include <mimimi.h>
5
6static signed char mimimi_sine[] = {0, 3, 6, 9, 12, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52, 55, 57, 60, 63, 66, 68, 71, 73, 76, 78, 81, 83, 86, 88, 90, 92, 94, 97, 99, 101, 102, 104, 106, 108, 109, 111, 112, 114, 115, 117, 118, 119, 120, 121, 122, 123, 124, 124, 125, 126, 126, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 126, 126, 125, 124, 124, 123, 122, 121, 120, 119, 118, 117, 115, 114, 112, 111, 109, 108, 106, 104, 102, 101, 99, 97, 94, 92, 90, 88, 86, 83, 81, 78, 76, 73, 71, 68, 66, 63, 60, 57, 55, 52, 49, 46, 43, 40, 37, 34, 31, 28, 25, 22, 19, 16, 12, 9, 6, 3, 0, -3, -6, -9, -12, -16, -19, -22, -25, -28, -31, -34, -37, -40, -43, -46, -49, -52, -55, -57, -60, -63, -66, -68, -71, -73, -76, -78, -81, -83, -86, -88, -90, -92, -94, -97, -99, -101, -102, -104, -106, -108, -109, -111, -112, -114, -115, -117, -118, -119, -120, -121, -122, -123, -124, -124, -125, -126, -126, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -126, -126, -125, -124, -124, -123, -122, -121, -120, -119, -118, -117, -115, -114, -112, -111, -109, -108, -106, -104, -102, -101, -99, -97, -94, -92, -90, -88, -86, -83, -81, -78, -76, -73, -71, -68, -66, -63, -60, -57, -55, -52, -49, -46, -43, -40, -37, -34, -31, -28, -25, -22, -19, -16, -12, -9, -6, -3, 0, 3, 6, 9, 12, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52, 55, 57, 60, 63, 66, 68, 71, 73, 76, 78, 81, 83, 86, 88, 90, 92, 94, 97, 99, 101, 102, 104, 106, 108, 109, 111, 112, 114, 115, 117, 118, 119, 120, 121, 122, 123, 124, 124, 125, 126, 126, 127, 127, 127, 127, 127};
7static signed char *mimimi_cosine = mimimi_sine + 64;
8
9static int mimimi_div(int n, int q)
10{
11 if (n < 0) return (n + 1) / q - 1;
12 if (n > 0) return (n - 1) / q + 1;
13 return 0;
14}
15
16static int mimimi_mod(int n, int q)
17{
18 while (n < 0) n += q;
19 n %= q;
20 return n;
21}
22
23static unsigned char mimimi_layer_pixel(struct mimimi_layer *layer, unsigned char y_angle, int x, int y)
24{
25 int w, h;
26 int w0, w1;
27 int s;
28 int count;
29 int a;
30
31 h = layer->count;
32
33 if (y < 0) return 0;
34 if (y >= h) return 0;
35
36 w0 = layer->rows[y].width;
37 w1 = layer->rows[y].height;
38
39 s = 128 - mimimi_cosine[y_angle * 2 % 256];
40 w = s * w0 + (256 - s) * w1;
41 w /= 512;
42
43 if (x < -w) return 0;
44 if (x >= w) return 0;
45
46 count = layer->rows[y].count;
47
48 a = y_angle + 64;
49 a *= count;
50 a += 128;
51 a /= 256;
52 a += x;
53 a = mimimi_mod(a, count);
54
55 return layer->rows[y].colors[a];
56}
57
58static void mimimi_swap(int *x, int *y)
59{
60 int z;
61 z = *x;
62 *x = *y;
63 *y = z;
64}
65
66static void mimimi_layer(struct mimimi_image *image, struct mimimi_layer *layer, int x0, int y0, struct mimimi_pose_layer *pose_layer, int behind)
67{
68 int width, height;
69 unsigned char y_angle;
70 int z_angle;
71 int x, y;
72 int x1, y1;
73 unsigned char color;
74
75 width = image->width;
76 height = image->height;
77
78 y_angle = pose_layer->y_angle;
79 z_angle = mimimi_mod(pose_layer->z_angle, 4);
80
81 if (behind != 0) y_angle += 128;
82
83 if (z_angle == 0)
84 {
85 for (y = 0 ; y < height ; y++)
86 for (x = 0 ; x < width ; x++)
87 {
88 x1 = x + layer->x - x0;
89 y1 = y + layer->y - y0;
90
91 x1 += pose_layer->slant * (y - y0) / 256;
92
93 if (behind != 0) x1 = -x1 - 1;
94
95 color = mimimi_layer_pixel(layer, y_angle, x1, y1);
96 if (color != 0) image->colors[x + y * width] = color;
97 }
98 }
99
100 if (z_angle == 1)
101 {
102 for (y = 0 ; y < height ; y++)
103 for (x = 0 ; x < width ; x++)
104 {
105 x1 = x - layer->y - x0;
106 y1 = y + layer->x - y0;
107
108 y1 -= pose_layer->slant * (x - x0) / 256;
109
110 if (behind != 0) y1 = -y1 - 1;
111
112 color = mimimi_layer_pixel(layer, y_angle, y1, -x1);
113 if (color != 0) image->colors[x + y * width] = color;
114 }
115
116 return;
117 }
118
119 if (z_angle == 2)
120 {
121 for (y = 0 ; y < height ; y++)
122 for (x = 0 ; x < width ; x++)
123 {
124 x1 = x - layer->x - x0;
125 y1 = y - layer->y - y0;
126
127 x1 += pose_layer->slant * (y - y0) / 256;
128
129 if (behind != 0) x1 = -x1 + 1;
130
131 color = mimimi_layer_pixel(layer, y_angle, -x1, -y1);
132 if (color != 0) image->colors[x + y * width] = color;
133 }
134
135 return;
136 }
137
138 if (z_angle == 3)
139 {
140 for (y = 0 ; y < height ; y++)
141 for (x = 0 ; x < width ; x++)
142 {
143 x1 = x + layer->y - x0;
144 y1 = y - layer->x - y0;
145
146 y1 -= pose_layer->slant * (x - x0) / 256;
147
148 if (behind != 0) y1 = -y1 + 1;
149
150 color = mimimi_layer_pixel(layer, y_angle, -y1, x1);
151 if (color != 0) image->colors[x + y * width] = color;
152 }
153
154 return;
155 }
156}
157
158static void mimimi_apply_y_angle(struct mimimi_model *model, struct mimimi_layer *layers, struct mimimi_pose_layer *pose_layers)
159{
160 int i, parent_index;
161 struct mimimi_layer *layer;
162 struct mimimi_pose_layer *pose_layer;
163 int parent_y_angle;
164 unsigned char y_angle;
165 int sin, cos;
166 int x, z;
167
168 for (i = 0 ; i < model->count ; i++)
169 {
170 layer = layers + i;
171 pose_layer = pose_layers + i;
172 parent_index = model->layers[i].parent_index;
173
174 if (i == parent_index) continue;
175
176 parent_y_angle = pose_layers[parent_index].y_angle;
177 pose_layer->y_angle += parent_y_angle;
178
179 y_angle = parent_y_angle;
180
181 sin = mimimi_sine[y_angle];
182 cos = mimimi_cosine[y_angle];
183
184 x = layer->x;
185 z = layer->z;
186
187 layer->x = cos*x / 128 + sin*z / 128;
188 layer->z = cos*z / 128 - sin*x / 128;
189 }
190}
191
192static void mimimi_apply_z_angle(struct mimimi_model *model, struct mimimi_layer *layers, struct mimimi_pose_layer *pose_layers)
193{
194 int xs[0x80], ys[0x80];
195 int i;
196 struct mimimi_layer *layer;
197 struct mimimi_pose_layer *pose_layer;
198 int parent_index;
199 int z_angle;
200 int x, y;
201
202 for (i = 0 ; i < model->count ; i++)
203 {
204 layer = layers + i;
205 pose_layer = pose_layers + i;
206 parent_index = model->layers[i].parent_index;
207
208 xs[i] = layer->x;
209 ys[i] = layer->y;
210 if (i == parent_index) continue;
211 xs[i] += xs[parent_index];
212 ys[i] += ys[parent_index];
213
214 z_angle = mimimi_mod(pose_layer->z_angle, 4);
215
216 x = xs[i];
217 y = ys[i];
218 if (z_angle == 1) x = -x, mimimi_swap(&x, &y);
219 if (z_angle == 2) x = -x, y = -y;
220 if (z_angle == 3) y = -y, mimimi_swap(&x, &y);
221 layer->x = x - xs[parent_index];
222 layer->y = y - ys[parent_index];
223
224 if (z_angle == 1) xs[i] = -xs[i], mimimi_swap(xs + i, ys + i);
225 if (z_angle == 2) xs[i] = -xs[i], ys[i] = -ys[i];
226 if (z_angle == 3) ys[i] = -ys[i], mimimi_swap(xs + i, ys + i);
227 }
228}
229
230static void mimimi_apply_slant(struct mimimi_model *model, struct mimimi_layer *layers, struct mimimi_pose_layer *pose_layers)
231{
232 int ys[0x80];
233 int i;
234 struct mimimi_layer *layer;
235 struct mimimi_pose_layer *pose_layer;
236 int parent_index;
237
238 for (i = 0 ; i < model->count ; i++)
239 {
240 layer = layers + i;
241 pose_layer = pose_layers + i;
242 parent_index = model->layers[i].parent_index;
243
244 ys[i] = layer->y;
245 if (i == parent_index) continue;
246 ys[i] += ys[parent_index];
247
248 layer->x += pose_layer->slant * ys[i] / 256;
249 }
250}
251
252static void mimimi_absolutise(struct mimimi_model *model, struct mimimi_layer *layers, struct mimimi_pose_layer *pose_layers)
253{
254 int i;
255 struct mimimi_layer *layer;
256 struct mimimi_pose_layer *pose_layer;
257 int parent_index;
258
259 for (i = 0 ; i < model->count ; i++)
260 {
261 layer = layers + i;
262 pose_layer = pose_layers + i;
263 parent_index = model->layers[i].parent_index;
264 if (i == parent_index) continue;
265
266 layer->x += layers[parent_index].x;
267 layer->y += layers[parent_index].y;
268 layer->z += layers[parent_index].z;
269 layer->amplifier = layer->amplifier * layers[parent_index].amplifier / 32;
270
271 pose_layer->slant += pose_layers[parent_index].slant;
272 pose_layer->z_angle += pose_layers[parent_index].z_angle;
273 pose_layer->z_angle = mimimi_mod(pose_layer->z_angle, 4);
274 }
275}
276
277struct mimimi_half_layer
278{
279 int behind;
280 int z;
281 struct mimimi_layer *layer;
282 struct mimimi_pose_layer *pose_layer;
283};
284
285void mimimi_pose(struct mimimi_image *image, struct mimimi_model *model, struct mimimi_pose *pose)
286{
287 struct mimimi_layer layers[0x20], *layer;
288 struct mimimi_pose_layer pose_layers[0x20], *pose_layer;
289 struct mimimi_half_layer half_layers[0x40], *half_layer, half_layer0;
290 int i, j, k;
291 int x, y;
292 int a, b;
293
294 for (i = 0 ; i < model->count ; i++)
295 {
296 layer = layers + i;
297 *layer = *model->layers[i].layer;
298
299 pose_layer = pose_layers + i;
300
301 if (i < pose->count)
302 {
303 *pose_layer = pose->layers[i];
304 }
305 else
306 {
307 pose_layer->slant = 0;
308 pose_layer->y_angle = 0;
309 pose_layer->z_angle = 0;
310 }
311 }
312
313 mimimi_apply_y_angle(model, layers, pose_layers);
314 mimimi_apply_z_angle(model, layers, pose_layers);
315 mimimi_apply_slant(model, layers, pose_layers);
316 mimimi_absolutise(model, layers, pose_layers);
317
318 for (i = 0 ; i < model->count ; i++)
319 {
320 layer = layers + i;
321 pose_layer = pose_layers + i;
322
323 half_layers[i * 2 + 0].behind = 0;
324 half_layers[i * 2 + 0].z = layer->z * layer->amplifier + layer->width * 32;
325 half_layers[i * 2 + 0].layer = layer;
326 half_layers[i * 2 + 0].pose_layer = pose_layer;
327
328 half_layers[i * 2 + 1].behind = 1;
329 half_layers[i * 2 + 1].z = layer->z * layer->amplifier - layer->width * 32;
330 half_layers[i * 2 + 1].layer = layer;
331 half_layers[i * 2 + 1].pose_layer = pose_layer;
332 }
333
334
335 for (i = 0 ; i < model->count * 2 ; i++)
336 {
337 a = half_layers[i].z;
338
339 k = i;
340 for (j = i - 1 ; j >= 0 ; j--)
341 {
342 b = half_layers[j].z;
343 if (a >= b) break;
344
345 half_layer0 = half_layers[k];
346 half_layers[k] = half_layers[j];
347 half_layers[j] = half_layer0;
348
349 k = j;
350 }
351 }
352
353 for (y = 0 ; y < image->height ; y++)
354 for (x = 0 ; x < image->width ; x++)
355 image->colors[x + y * image->width] = 0;
356
357 for (i = 0 ; i < model->count * 2 ; i++)
358 {
359 half_layer = half_layers + i;
360 mimimi_layer(image, half_layer->layer, pose->x, pose->y, half_layer->pose_layer, half_layer->behind);
361 }
362}
363
364static void mimimi_interpolate_pose_layer(struct mimimi_pose_layer *a, struct mimimi_pose_layer *b, int i, int count)
365{
366 int slant, y_angle, z_angle;
367
368 slant = a->slant * (count - i) / count;
369 slant += mimimi_div(b->slant * i, count);
370
371 y_angle = a->y_angle * (count - i) / count;
372 y_angle += mimimi_div(b->y_angle * i, count);
373
374 z_angle = a->z_angle * (count - i) / count;
375 z_angle += mimimi_div(b->z_angle * i, count);
376
377 a->slant = slant;
378 a->y_angle = y_angle;
379 a->z_angle = z_angle;
380}
381
382static void mimimi_interpolate_pose(struct mimimi_pose *a, struct mimimi_pose *b, int i, int count)
383{
384 int x, y;
385 int j;
386
387 if (count == 0) return;
388
389 x = a->x * (count - i) / count;
390 x += mimimi_div(b->x * i, count);
391
392 y = a->y * (count - i) / count;
393 y += mimimi_div(b->y * i, count);
394
395 a->x = x;
396 a->y = y;
397
398 for (j = 0 ; j < a->count ; j++)
399 mimimi_interpolate_pose_layer(a->layers + j, b->layers + j, i, count);
400}
401
402void mimimi_movement(struct mimimi_video *video, struct mimimi_model *model, struct mimimi_movement *movement)
403{
404 int h, i, j, k;
405 struct mimimi_pose pose;
406
407 if (movement->count == 1)
408 {
409 for (i = 0 ; i < video->count ; i++)
410 mimimi_pose(video->images + i, model, movement->poses);
411 return;
412 }
413
414 for (i = 0 ; i < video->count ; i++)
415 {
416 j = i * (movement->count - 1) / video->count;
417 k = i - j * video->count / (movement->count - 1);
418
419 pose = movement->poses[j];
420 for (h = 0 ; h < pose.count ; h++) pose.layers[h] = movement->poses[j].layers[h];
421
422 mimimi_interpolate_pose(&pose, movement->poses + j + 1, k, video->count / (movement->count - 1));
423 mimimi_pose(video->images + i, model, &pose);
424 }
425}
426
427static void mimimi_appearance_videos(struct mimimi_video_set *videos, struct mimimi_model *model, int x, int y, int coefficient)
428{
429 static struct mimimi_pose_layer layer0 = {0};
430
431 int video_count;
432 int i, j;
433 int slant, y_angle;
434 struct mimimi_pose poses[3], pose;
435 struct mimimi_movement movement;
436 struct mimimi_pose_layer layers[2][10];
437
438 video_count = videos->standing_video_count;
439 for (i = 0 ; i < video_count ; i++)
440 {
441 slant = 512 * i / video_count * coefficient;
442 y_angle = 64 + (20 + 20 * i / video_count) * coefficient;
443
444 for (j = 0 ; j < 10 ; j++)
445 {
446 layers[0][j] = layer0;
447 layers[1][j] = layer0;
448 }
449
450 layers[0][0].y_angle = y_angle;
451 layers[1][0].y_angle = y_angle;
452
453 layers[0][0].slant = -slant / 8;
454 layers[1][0].slant = -slant / 8;
455
456 layers[0][1].slant = slant / 8;
457 layers[1][1].slant = slant / 8;
458
459 layers[1][4].slant = slant / 3;
460 layers[1][8].slant = -slant / 3;
461 layers[0][8].slant = -slant / 8;
462
463 layers[0][5].slant = slant / 3;
464 layers[0][9].slant = -slant / 3;
465 layers[1][9].slant = -slant / 8;
466
467 layers[0][2].slant = slant / 5;
468 layers[1][2].slant = -slant / 3;
469 layers[0][6].slant = slant / 4;
470 layers[1][6].slant = slant / 2;
471
472 layers[1][3].slant = slant / 5;
473 layers[0][3].slant = -slant / 3;
474 layers[1][7].slant = slant / 4;
475 layers[0][7].slant = slant / 2;
476
477 for (j = 0 ; j < 3 ; j++)
478 {
479 poses[j].x = x;
480 poses[j].y = y;
481 poses[j].count = 10;
482 }
483
484 for (j = 0 ; j < 10 ; j++)
485 {
486 poses[0].layers[j] = layers[0][j];
487 poses[1].layers[j] = layers[1][j];
488 poses[2].layers[j] = layers[0][j];
489 }
490
491 movement.count = 3;
492 movement.poses = poses;
493 mimimi_movement(videos->standing + i, model, &movement);
494 }
495
496 for (i = 0 ; i < 7 ; i++) pose.layers[i] = layer0;
497
498 pose.layers[0].z_angle = coefficient;
499 pose.layers[0].y_angle = 64 + 32 * coefficient;
500 pose.layers[4].slant = 96 * coefficient;
501 pose.layers[5].slant = 96 * coefficient;
502 pose.layers[2].z_angle = coefficient;
503 pose.layers[2].slant = -96;
504 pose.layers[3].z_angle = coefficient;
505 pose.layers[3].slant = 96;
506
507 pose.x = x - 12 * coefficient;
508 pose.y = y - 12;
509 pose.count = 7;
510
511 movement.count = 1;
512 movement.poses = &pose;
513
514 mimimi_movement(videos->falling, model, &movement);
515
516 pose.layers[0] = layer0;
517 pose.layers[0].slant = 0;
518 pose.layers[0].z_angle = coefficient;
519 pose.layers[0].y_angle = 64 + 32 * coefficient;
520
521 pose.x = x - 12 * coefficient;
522 pose.y = y - 20;
523 pose.count = 1;
524
525 movement.count = 1;
526 movement.poses = &pose;
527
528 mimimi_movement(videos->knocked, model, &movement);
529
530 video_count = videos->jumping_video_count;
531 for (i = 0 ; i < video_count ; i++)
532 {
533 for (j = 0 ; j < 6 ; j++)
534 {
535 poses[0].layers[j] = layer0;
536 poses[1].layers[j] = layer0;
537 }
538
539 slant = 64 * i / videos->jumping[i].count * coefficient;
540 y_angle = 64 + (20 + 20 * i / videos->jumping[i].count) * coefficient;
541
542 poses[0].x = x;
543 poses[0].y = y;
544 poses[0].count = 6;
545 poses[0].layers[0].y_angle = y_angle;
546 poses[0].layers[0].slant = -slant * 2;
547 poses[0].layers[1].slant = slant * 2;
548 poses[0].layers[4].slant = -slant / 2;
549 poses[0].layers[5].slant = -slant / 2;
550
551 poses[1].x = x;
552 poses[1].y = y;
553 poses[1].count = 6;
554 poses[1].layers[0].y_angle = y_angle;
555 poses[1].layers[2].slant = -slant * 2;
556 poses[1].layers[3].slant = -slant * 2;
557 poses[1].layers[4].slant = slant * 2;
558 poses[1].layers[5].slant = slant * 2;
559
560 movement.count = 2;
561 movement.poses = poses;
562
563 mimimi_movement(videos->jumping + i, model, &movement);
564 }
565}
566
567void mimimi_appearance(struct mimimi_appearance *appearance, struct mimimi_model *model, int x, int y)
568{
569 mimimi_appearance_videos(&appearance->left, model, x, y, 1);
570 mimimi_appearance_videos(&appearance->right, model, x, y, -1);
571}