Первый движок анимации
This commit is contained in:
@@ -24,6 +24,7 @@ int main(void) {
|
|||||||
printf("FIG_ANGLE equ %zu\n", offsetof(struct figure_animation_info, angle));
|
printf("FIG_ANGLE equ %zu\n", offsetof(struct figure_animation_info, angle));
|
||||||
printf("FIG_ANG_VEL equ %zu\n", offsetof(struct figure_animation_info, angular_velocity));
|
printf("FIG_ANG_VEL equ %zu\n", offsetof(struct figure_animation_info, angular_velocity));
|
||||||
printf("FIG_SPEED equ %zu\n", offsetof(struct figure_animation_info, speed));
|
printf("FIG_SPEED equ %zu\n", offsetof(struct figure_animation_info, speed));
|
||||||
|
printf("FIG_RADIUS equ %zu\n", offsetof(struct figure_animation_info, radius));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
9
wayland/include/figure-draw.h
Normal file
9
wayland/include/figure-draw.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef FIGURE_DRAW_H
|
||||||
|
#define FIGURE_ANFIGURE_DRAW_HIMATE_H
|
||||||
|
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
/* Нарисовать фигуру на холсте */
|
||||||
|
void figure_draw(struct window_draw_info* draw_info, float border_thikness, uint32_t border_color, uint32_t fill_color);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -19,6 +19,10 @@ struct figure_animation_info {
|
|||||||
float angular_velocity;
|
float angular_velocity;
|
||||||
|
|
||||||
float speed;
|
float speed;
|
||||||
|
/* Radius of the figure normalized for window width (0..1)
|
||||||
|
* This field is used by animation code to check collisions
|
||||||
|
* with the left/right/top/bottom borders. */
|
||||||
|
float radius;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,32 +8,155 @@ section .text
|
|||||||
; rdi - указатель на struct window_draw_info
|
; rdi - указатель на struct window_draw_info
|
||||||
global figure_animation_step
|
global figure_animation_step
|
||||||
figure_animation_step:
|
figure_animation_step:
|
||||||
|
; Создаём локальную область на стеке и будем туда копировать поля структуры
|
||||||
enter 0, 0
|
enter 0, 0
|
||||||
|
; rdi - pointer to struct window_draw_info
|
||||||
; Сохранение регистров (если будут использоваться)
|
; figure is embedded at offset WDI_FIGURE
|
||||||
; push rbx
|
mov rax, rdi
|
||||||
; push r12
|
add rax, WDI_FIGURE
|
||||||
; push r13
|
|
||||||
|
; --- compute movement scale: scale = speed * (dt / BASE_SIZE)
|
||||||
; rdi содержит указатель на window_draw_info
|
; using SSE for float math
|
||||||
; Доступ к полям через константы из offsets.inc:
|
movss xmm0, dword [rax + FIG_SPEED] ; xmm0 = speed
|
||||||
mov rax, WDI_FIGURE ; указатель на данные
|
mulss xmm0, [rel SCALE_FACTOR] ; xmm0 = speed * (dt / BASE_SIZE)
|
||||||
; mov edx, [rdi + WD_WIDTH] ; ширина окна
|
|
||||||
; mov ecx, [rdi + WD_HEIGHT] ; высота окна
|
; dx = velocity.x * scale
|
||||||
; lea rsi, [rdi + WD_FIGURE] ; указатель на figure_animation_info
|
movss xmm1, dword [rax + FIG_VELOCITY] ; velocity.x
|
||||||
;
|
mulss xmm1, xmm0
|
||||||
; Доступ к полям figure_animation_info (относительно rsi):
|
movss xmm2, dword [rax + FIG_POSITION] ; position.x
|
||||||
; mov eax, [rsi + FIG_TYPE] ; тип фигуры
|
addss xmm2, xmm1
|
||||||
; movss xmm0, [rsi + FIG_ANGLE] ; угол поворота
|
movss dword [rax + FIG_POSITION], xmm2
|
||||||
; movss xmm1, [rsi + FIG_SPEED] ; скорость
|
|
||||||
|
; dy = velocity.y * scale
|
||||||
; --- Здесь будет логика анимации ---
|
movss xmm1, dword [rax + FIG_VELOCITY + 4]
|
||||||
|
mulss xmm1, xmm0
|
||||||
|
movss xmm2, dword [rax + FIG_POSITION + 4]
|
||||||
; Восстановление регистров
|
addss xmm2, xmm1
|
||||||
; pop r13
|
movss dword [rax + FIG_POSITION + 4], xmm2
|
||||||
; pop r12
|
|
||||||
; pop rbx
|
; rotate: angle += angular_velocity * dt
|
||||||
|
movss xmm3, dword [rax + FIG_ANG_VEL]
|
||||||
|
mulss xmm3, [rel DT]
|
||||||
|
movss xmm4, dword [rax + FIG_ANGLE]
|
||||||
|
addss xmm4, xmm3
|
||||||
|
movss dword [rax + FIG_ANGLE], xmm4
|
||||||
|
|
||||||
|
; If circle -> call collision check helper
|
||||||
|
mov ecx, dword [rax + FIG_TYPE]
|
||||||
|
cmp ecx, 0
|
||||||
|
jne .no_collision_check
|
||||||
|
; pass pointer to window_draw_info (original rdi) in rdi
|
||||||
|
; rdi already has draw_info pointer
|
||||||
|
call figure_check_collision_circle
|
||||||
|
|
||||||
|
.no_collision_check:
|
||||||
|
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; helper: check collision for circle and reflect velocity & angular velocity
|
||||||
|
; rdi - pointer to struct window_draw_info
|
||||||
|
global figure_check_collision_circle
|
||||||
|
figure_check_collision_circle:
|
||||||
|
push rbx
|
||||||
|
; rdi -> window_draw_info
|
||||||
|
; rax -> figure_animation_info
|
||||||
|
mov rax, rdi
|
||||||
|
add rax, WDI_FIGURE
|
||||||
|
|
||||||
|
movss xmm0, dword [rax + FIG_POSITION] ; pos.x
|
||||||
|
movss xmm1, dword [rax + FIG_POSITION + 4] ; pos.y
|
||||||
|
|
||||||
|
movss xmm2, dword [rax + FIG_VELOCITY] ; vel.x
|
||||||
|
movss xmm3, dword [rax + FIG_VELOCITY + 4] ; vel.y
|
||||||
|
|
||||||
|
movss xmm4, dword [rax + FIG_ANG_VEL] ; angvel
|
||||||
|
|
||||||
|
; radius is stored in figure as normalized relative to window width
|
||||||
|
movss xmm5, dword [rax + FIG_RADIUS]
|
||||||
|
|
||||||
|
; compute normalized radius for Y: r_y = radius * (width / height)
|
||||||
|
; load width/height from window_draw_info
|
||||||
|
mov ebx, dword [rdi + WDI_WIDTH]
|
||||||
|
cvtsi2ss xmm10, ebx
|
||||||
|
mov ebx, dword [rdi + WDI_HEIGHT]
|
||||||
|
cvtsi2ss xmm11, ebx
|
||||||
|
divss xmm10, xmm11 ; xmm10 = width/height
|
||||||
|
movss xmm12, xmm5
|
||||||
|
mulss xmm12, xmm10 ; xmm12 = radius_y
|
||||||
|
|
||||||
|
; left edge: pos.x < radius ?
|
||||||
|
ucomiss xmm0, xmm5
|
||||||
|
jae .check_right
|
||||||
|
; pos.x = radius
|
||||||
|
movss dword [rax + FIG_POSITION], xmm5
|
||||||
|
; vel.x = -vel.x
|
||||||
|
movss xmm6, xmm2
|
||||||
|
mulss xmm6, [rel NEG_ONE]
|
||||||
|
movss dword [rax + FIG_VELOCITY], xmm6
|
||||||
|
; invert angular velocity
|
||||||
|
movss xmm7, xmm4
|
||||||
|
mulss xmm7, [rel NEG_ONE]
|
||||||
|
movss dword [rax + FIG_ANG_VEL], xmm7
|
||||||
|
jmp .done_x
|
||||||
|
|
||||||
|
.check_right:
|
||||||
|
; pos.x + radius > 1 ?
|
||||||
|
movss xmm8, [rel ONE_CONST]
|
||||||
|
addss xmm8, xmm5 ; xmm8 = 1 + radius
|
||||||
|
; Actually want pos.x + radius > 1 <=> pos.x > 1 - radius
|
||||||
|
; compute bound = 1 - radius
|
||||||
|
movss xmm9, [rel ONE_CONST]
|
||||||
|
subss xmm9, xmm5
|
||||||
|
ucomiss xmm0, xmm9
|
||||||
|
jbe .done_x
|
||||||
|
; pos.x = 1 - radius
|
||||||
|
movss dword [rax + FIG_POSITION], xmm9
|
||||||
|
; vel.x = -vel.x
|
||||||
|
movss xmm6, xmm2
|
||||||
|
mulss xmm6, [rel NEG_ONE]
|
||||||
|
movss dword [rax + FIG_VELOCITY], xmm6
|
||||||
|
; invert angular velocity
|
||||||
|
movss xmm7, xmm4
|
||||||
|
mulss xmm7, [rel NEG_ONE]
|
||||||
|
movss dword [rax + FIG_ANG_VEL], xmm7
|
||||||
|
|
||||||
|
.done_x:
|
||||||
|
; check bottom / top boundaries for y
|
||||||
|
; bottom: pos.y < radius
|
||||||
|
ucomiss xmm1, xmm12
|
||||||
|
jae .check_top2
|
||||||
|
movss dword [rax + FIG_POSITION + 4], xmm12
|
||||||
|
movss xmm6, xmm3
|
||||||
|
mulss xmm6, [rel NEG_ONE]
|
||||||
|
movss dword [rax + FIG_VELOCITY + 4], xmm6
|
||||||
|
; invert angular
|
||||||
|
movss xmm7, xmm4
|
||||||
|
mulss xmm7, [rel NEG_ONE]
|
||||||
|
movss dword [rax + FIG_ANG_VEL], xmm7
|
||||||
|
jmp .done_y
|
||||||
|
|
||||||
|
.check_top2:
|
||||||
|
; top: pos.y > 1 - radius
|
||||||
|
movss xmm9, [rel ONE_CONST]
|
||||||
|
subss xmm9, xmm5
|
||||||
|
ucomiss xmm1, xmm9
|
||||||
|
jbe .done_y
|
||||||
|
movss dword [rax + FIG_POSITION + 4], xmm9
|
||||||
|
movss xmm6, xmm3
|
||||||
|
mulss xmm6, [rel NEG_ONE]
|
||||||
|
movss dword [rax + FIG_VELOCITY + 4], xmm6
|
||||||
|
movss xmm7, xmm4
|
||||||
|
mulss xmm7, [rel NEG_ONE]
|
||||||
|
movss dword [rax + FIG_ANG_VEL], xmm7
|
||||||
|
|
||||||
|
.done_y:
|
||||||
|
pop rbx
|
||||||
|
ret
|
||||||
|
|
||||||
|
section .rodata
|
||||||
|
SCALE_FACTOR: dd 0.001
|
||||||
|
DT: dd 0.1
|
||||||
|
NEG_ONE: dd -1.0
|
||||||
|
ONE_CONST: dd 1.0
|
||||||
|
|||||||
@@ -242,6 +242,18 @@ int window_init(struct wl_display *display, struct wl_event_queue *queue, struct
|
|||||||
draw_info->width = 400;
|
draw_info->width = 400;
|
||||||
draw_info->height = 250;
|
draw_info->height = 250;
|
||||||
draw_info->data = NULL;
|
draw_info->data = NULL;
|
||||||
|
|
||||||
|
/* Default animation state */
|
||||||
|
draw_info->figure.type = FIGURE_CIRCLE;
|
||||||
|
draw_info->figure.position.x = 0.5f;
|
||||||
|
draw_info->figure.position.y = 0.5f;
|
||||||
|
draw_info->figure.velocity.x = 0.6f;
|
||||||
|
draw_info->figure.velocity.y = 0.3f;
|
||||||
|
draw_info->figure.angle = 0.0f;
|
||||||
|
draw_info->figure.angular_velocity = 1.0f; /* radians per second */
|
||||||
|
draw_info->figure.speed = 30.0f; /* pixels per second baseline (norm by width) */
|
||||||
|
draw_info->figure.radius = 0.05f; /* normalized relative to width: 5% */
|
||||||
|
|
||||||
win->buffer = NULL;
|
win->buffer = NULL;
|
||||||
win->frame_callback = NULL;
|
win->frame_callback = NULL;
|
||||||
win->need_close = 0;
|
win->need_close = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user