Mirai's Miscellaneous Misadventures

M52 / core / animations.c

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