Mirai's Miscellaneous Misadventures

M44 / core / animations.c

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