Mirai's Miscellaneous Misadventures

M51 / core / animations.c

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