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