Первый движок анимации
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_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_RADIUS equ %zu\n", offsetof(struct figure_animation_info, radius));
|
||||
|
||||
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 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
|
||||
|
||||
@@ -8,32 +8,155 @@ section .text
|
||||
; rdi - указатель на struct window_draw_info
|
||||
global figure_animation_step
|
||||
figure_animation_step:
|
||||
; Создаём локальную область на стеке и будем туда копировать поля структуры
|
||||
enter 0, 0
|
||||
; rdi - pointer to struct window_draw_info
|
||||
; figure is embedded at offset WDI_FIGURE
|
||||
mov rax, rdi
|
||||
add rax, WDI_FIGURE
|
||||
|
||||
; Сохранение регистров (если будут использоваться)
|
||||
; push rbx
|
||||
; push r12
|
||||
; push r13
|
||||
; --- compute movement scale: scale = speed * (dt / BASE_SIZE)
|
||||
; using SSE for float math
|
||||
movss xmm0, dword [rax + FIG_SPEED] ; xmm0 = speed
|
||||
mulss xmm0, [rel SCALE_FACTOR] ; xmm0 = speed * (dt / BASE_SIZE)
|
||||
|
||||
; rdi содержит указатель на window_draw_info
|
||||
; Доступ к полям через константы из offsets.inc:
|
||||
mov rax, WDI_FIGURE ; указатель на данные
|
||||
; mov edx, [rdi + WD_WIDTH] ; ширина окна
|
||||
; mov ecx, [rdi + WD_HEIGHT] ; высота окна
|
||||
; lea rsi, [rdi + WD_FIGURE] ; указатель на figure_animation_info
|
||||
;
|
||||
; Доступ к полям figure_animation_info (относительно rsi):
|
||||
; mov eax, [rsi + FIG_TYPE] ; тип фигуры
|
||||
; movss xmm0, [rsi + FIG_ANGLE] ; угол поворота
|
||||
; movss xmm1, [rsi + FIG_SPEED] ; скорость
|
||||
; dx = velocity.x * scale
|
||||
movss xmm1, dword [rax + FIG_VELOCITY] ; velocity.x
|
||||
mulss xmm1, xmm0
|
||||
movss xmm2, dword [rax + FIG_POSITION] ; position.x
|
||||
addss xmm2, xmm1
|
||||
movss dword [rax + FIG_POSITION], xmm2
|
||||
|
||||
; --- Здесь будет логика анимации ---
|
||||
; dy = velocity.y * scale
|
||||
movss xmm1, dword [rax + FIG_VELOCITY + 4]
|
||||
mulss xmm1, xmm0
|
||||
movss xmm2, dword [rax + FIG_POSITION + 4]
|
||||
addss xmm2, xmm1
|
||||
movss dword [rax + FIG_POSITION + 4], xmm2
|
||||
|
||||
; 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
|
||||
|
||||
; Восстановление регистров
|
||||
; pop r13
|
||||
; pop r12
|
||||
; pop rbx
|
||||
; 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
|
||||
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->height = 250;
|
||||
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->frame_callback = NULL;
|
||||
win->need_close = 0;
|
||||
|
||||
Reference in New Issue
Block a user