Mirai's Miscellaneous Misadventures
M54 / 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 || y >= h) return 0;
17
18 w0 = layer->rows[y].width;
19 w1 = layer->rows[y].height;
20
21 s = 128 - mimimi_cosine[y_angle * 16 % 2048];
22 w = s * w0 + (256 - s) * w1;
23 w /= 512;
24
25 if (x < -w || x >= w) return 0;
26
27 count = layer->rows[y].count;
28
29 a = y_angle + 64;
30 a *= count;
31 a += 128;
32 a /= 256;
33 a += x;
34 a = mimimi_mod(a, count);
35
36 return layer->rows[y].colors[a];
37}
38
39static void mimimi_swap(int *a, int *b)
40{
41 int c;
42 c = *a;
43 *a = *b;
44 *b = c;
45}
46
47static void mimimi_layer(struct mimimi_image *image, struct mimimi_layer *layer, int x0, int y0, struct mimimi_pose_layer *pose_layer, int behind)
48{
49 int width, height;
50 unsigned char y_angle;
51 int z_angle;
52 int x, y;
53 int x1, y1;
54 unsigned char color;
55
56 width = image->width;
57 height = image->height;
58
59 y_angle = pose_layer->y_angle;
60 z_angle = mimimi_mod(pose_layer->z_angle, 4);
61
62 if (behind != 0) y_angle += 128;
63
64 if (z_angle == 0) {
65
66 for (y = 0 ; y < height ; y++) {
67
68 for (x = 0 ; x < width ; x++) {
69
70 x1 = x + layer->x - x0;
71 y1 = y + layer->y - y0;
72
73 x1 += pose_layer->slant * (y - y0) / 256;
74
75 if (behind != 0) x1 = -x1 - 1;
76
77 color = mimimi_layer_pixel(layer, y_angle, x1, y1);
78 if (color != 0) image->colors[x + y * width] = color;
79 }
80 }
81 }
82
83 if (z_angle == 1) {
84
85 for (y = 0 ; y < height ; y++) {
86
87 for (x = 0 ; x < width ; x++) {
88
89 x1 = x - layer->y - x0;
90 y1 = y + layer->x - y0;
91
92 y1 -= pose_layer->slant * (x - x0) / 256;
93
94 if (behind != 0) y1 = -y1 - 1;
95
96 color = mimimi_layer_pixel(layer, y_angle, y1, -x1);
97 if (color != 0) image->colors[x + y * width] = color;
98 }
99 }
100 }
101
102 if (z_angle == 2) {
103
104 for (y = 0 ; y < height ; y++) {
105
106 for (x = 0 ; x < width ; x++) {
107
108 x1 = x - layer->x - x0;
109 y1 = y - layer->y - y0;
110
111 x1 += pose_layer->slant * (y - y0) / 256;
112
113 if (behind != 0) x1 = -x1 + 1;
114
115 color = mimimi_layer_pixel(layer, y_angle, -x1, -y1);
116 if (color != 0) image->colors[x + y * width] = color;
117 }
118 }
119 }
120
121 if (z_angle == 3) {
122
123 for (y = 0 ; y < height ; y++) {
124
125 for (x = 0 ; x < width ; x++) {
126
127 x1 = x + layer->y - x0;
128 y1 = y - layer->x - y0;
129
130 y1 -= pose_layer->slant * (x - x0) / 256;
131
132 if (behind != 0) y1 = -y1 + 1;
133
134 color = mimimi_layer_pixel(layer, y_angle, -y1, x1);
135 if (color != 0) image->colors[x + y * width] = color;
136 }
137 }
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 * 8];
165 cos = mimimi_cosine[y_angle * 8];
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 static int xs[0x80], ys[0x80];
178
179 int i;
180 struct mimimi_layer *layer;
181 struct mimimi_pose_layer *pose_layer;
182 int parent_index;
183 int z_angle;
184 int x, y;
185
186 for (i = 0 ; i < model->count ; i++) {
187
188 layer = layers + i;
189 pose_layer = pose_layers + i;
190 parent_index = model->layers[i].parent_index;
191
192 xs[i] = layer->x;
193 ys[i] = layer->y;
194 if (i == parent_index) continue;
195 xs[i] += xs[parent_index];
196 ys[i] += ys[parent_index];
197
198 z_angle = mimimi_mod(pose_layer->z_angle, 4);
199
200 x = xs[i];
201 y = ys[i];
202 if (z_angle == 1) {
203 x = -x;
204 mimimi_swap(&x, &y);
205 }
206 if (z_angle == 2) {
207 x = -x;
208 y = -y;
209 }
210 if (z_angle == 3) {
211 y = -y;
212 mimimi_swap(&x, &y);
213 }
214 layer->x = x - xs[parent_index];
215 layer->y = y - ys[parent_index];
216
217 if (z_angle == 1) {
218 xs[i] = -xs[i];
219 mimimi_swap(xs + i, ys + i);
220 }
221 if (z_angle == 2) {
222 xs[i] = -xs[i];
223 ys[i] = -ys[i];
224 }
225 if (z_angle == 3) {
226 ys[i] = -ys[i];
227 mimimi_swap(xs + i, ys + i);
228 }
229 }
230}
231
232static void mimimi_apply_slant(struct mimimi_model *model, struct mimimi_layer *layers, struct mimimi_pose_layer *pose_layers)
233{
234 static int ys[0x80];
235
236 int i;
237 struct mimimi_layer *layer;
238 struct mimimi_pose_layer *pose_layer;
239 int parent_index;
240
241 for (i = 0 ; i < model->count ; i++) {
242
243 layer = layers + i;
244 pose_layer = pose_layers + i;
245 parent_index = model->layers[i].parent_index;
246
247 ys[i] = layer->y + pose_layer->y;
248 if (i == parent_index) continue;
249 ys[i] += ys[parent_index];
250
251 layer->x += pose_layer->slant * ys[i] / 256;
252 }
253}
254
255static void mimimi_absolutise(struct mimimi_model *model, struct mimimi_layer *layers, struct mimimi_pose_layer *pose_layers)
256{
257 int i;
258 struct mimimi_layer *layer;
259 struct mimimi_pose_layer *pose_layer;
260 int parent_index;
261
262 for (i = 0 ; i < model->count ; i++) {
263
264 layer = layers + i;
265 pose_layer = pose_layers + i;
266 parent_index = model->layers[i].parent_index;
267
268 layer->y += pose_layer->y;
269
270 if (i == parent_index) continue;
271
272 layer->x += layers[parent_index].x;
273 layer->y += layers[parent_index].y;
274 layer->z += layers[parent_index].z;
275 layer->amplifier = layer->amplifier * layers[parent_index].amplifier / 32;
276
277 pose_layer->slant += pose_layers[parent_index].slant;
278 pose_layer->z_angle += pose_layers[parent_index].z_angle;
279 pose_layer->z_angle = mimimi_mod(pose_layer->z_angle, 4);
280 }
281}
282
283struct mimimi_half_layer {
284 int behind;
285 int z;
286 struct mimimi_layer *layer;
287 struct mimimi_pose_layer *pose_layer;
288};
289
290void mimimi_pose(struct mimimi_image *image, struct mimimi_model *model, struct mimimi_pose *pose)
291{
292 static struct mimimi_layer layers[0x80];
293 static struct mimimi_pose_layer pose_layers[0x80];
294 static struct mimimi_half_layer half_layers[0x100];
295
296 struct mimimi_layer *layer;
297 struct mimimi_pose_layer *pose_layer;
298 struct mimimi_half_layer *half_layer, half_layer0;
299 int i, j, k;
300 int a, b;
301
302 for (i = 0 ; i < model->count ; i++) {
303 layers[i] = *model->layers[i].layer;
304 pose_layers[i] = pose->layers[i];
305 }
306
307 mimimi_apply_y_angle(model, layers, pose_layers);
308 mimimi_apply_z_angle(model, layers, pose_layers);
309 mimimi_apply_slant(model, layers, pose_layers);
310 mimimi_absolutise(model, layers, pose_layers);
311
312 for (i = 0 ; i < model->count ; i++) {
313
314 layer = layers + i;
315 pose_layer = pose_layers + i;
316
317 half_layers[i * 2 + 0].behind = 0;
318 half_layers[i * 2 + 0].z = layer->z * layer->amplifier + layer->width * 32;
319 half_layers[i * 2 + 0].layer = layer;
320 half_layers[i * 2 + 0].pose_layer = pose_layer;
321
322 half_layers[i * 2 + 1].behind = 1;
323 half_layers[i * 2 + 1].z = layer->z * layer->amplifier - layer->width * 32;
324 half_layers[i * 2 + 1].layer = layer;
325 half_layers[i * 2 + 1].pose_layer = pose_layer;
326 }
327
328
329 for (i = 0 ; i < model->count * 2 ; i++) {
330
331 a = half_layers[i].z;
332
333 k = i;
334 for (j = i - 1 ; j >= 0 ; j--) {
335
336 b = half_layers[j].z;
337 if (a >= b) break;
338
339 half_layer0 = half_layers[k];
340 half_layers[k] = half_layers[j];
341 half_layers[j] = half_layer0;
342
343 k = j;
344 }
345 }
346
347 for (i = 0 ; i < model->count * 2 ; i++) {
348 half_layer = half_layers + i;
349 mimimi_layer(image, half_layer->layer, pose->x, pose->y, half_layer->pose_layer, half_layer->behind);
350 }
351}
352
353static void mimimi_interpolate_layer(struct mimimi_pose_layer *a, struct mimimi_pose_layer *b, int i, int count)
354{
355 int y, slant, y_angle, z_angle;
356
357 y = a->y * (count - i);
358 y += b->y * i;
359
360 slant = a->slant * (count - i);
361 slant += b->slant * i;
362
363 y_angle = a->y_angle * (count - i);
364 y_angle += b->y_angle * i;
365
366 z_angle = a->z_angle * (count - i);
367 z_angle += b->z_angle * i;
368
369 a->y = mimimi_div(y, count);
370 a->slant = mimimi_div(slant, count);
371 a->y_angle = mimimi_div(y_angle, count);
372 a->z_angle = mimimi_div(z_angle, count);
373}
374
375void mimimi_interpolate(struct mimimi_pose *a, struct mimimi_pose *b, int i, int count)
376{
377 int x, y;
378 int j;
379
380 i = 128 - mimimi_cosine[i * 1024 / count];
381 count = 256;
382
383 x = a->x * (count - i);
384 x += b->x * i;
385
386 y = a->y * (count - i);
387 y += b->y * i;
388
389 a->x = mimimi_div(x, count);
390 a->y = mimimi_div(y, count);
391
392 for (j = 0 ; j < (int) (sizeof a->layers / sizeof *a->layers) ; j++) mimimi_interpolate_layer(a->layers + j, b->layers + j, i, count);
393}