Mirai's Miscellaneous Misadventures

M43 / core / animations.c

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