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