Рабочий прототип
This commit is contained in:
@@ -22,66 +22,38 @@ section .text
|
||||
%assign __local_offset 0
|
||||
global figure_animation_step
|
||||
figure_animation_step:
|
||||
; Создаём локальную область на стеке и будем туда копировать поля структуры
|
||||
enter 48, 0
|
||||
enter 0, 0
|
||||
|
||||
; Отработка коллизий
|
||||
call figure_handle_collision;
|
||||
push rdi
|
||||
call figure_handle_collision
|
||||
pop rdi
|
||||
|
||||
; Сохранить регистры
|
||||
; Вычислить нормализующий коэффициент: 1.0 / height_pixels
|
||||
cvtsi2ss xmm4, dword [rdi + WDI_HEIGHT]
|
||||
movss xmm5, [rel ONE_CONST]
|
||||
divss xmm5, xmm4 ; xmm5 = 1.0 / height
|
||||
|
||||
; Сдвиги переменных
|
||||
; Аргументы
|
||||
local width, 4
|
||||
local height, 4
|
||||
local fig_type, 4
|
||||
local pos_x, 4
|
||||
local pos_y, 4
|
||||
local vel_x, 4
|
||||
local vel_y, 4
|
||||
local angle, 4
|
||||
local angular_vel, 4
|
||||
local speed, 4
|
||||
local radius, 4
|
||||
; Обновить позицию: position += (velocity * speed) / height_pixels
|
||||
; pos_x += (vel_x * speed) / height
|
||||
movss xmm0, [rdi + WDI_FIGURE + FIG_VELOCITY]
|
||||
mulss xmm0, [rdi + WDI_FIGURE + FIG_SPEED]
|
||||
mulss xmm0, xmm5 ; нормализовать скорость
|
||||
addss xmm0, [rdi + WDI_FIGURE + FIG_POSITION]
|
||||
movss [rdi + WDI_FIGURE + FIG_POSITION], xmm0
|
||||
|
||||
; Чтение аргументов
|
||||
mov eax, dword [rdi + WDI_WIDTH]
|
||||
mov [rbp - width], eax
|
||||
; pos_y += (vel_y * speed) / height
|
||||
movss xmm0, [rdi + WDI_FIGURE + FIG_VELOCITY + 4]
|
||||
mulss xmm0, [rdi + WDI_FIGURE + FIG_SPEED]
|
||||
mulss xmm0, xmm5 ; нормализовать скорость
|
||||
addss xmm0, [rdi + WDI_FIGURE + FIG_POSITION + 4]
|
||||
movss [rdi + WDI_FIGURE + FIG_POSITION + 4], xmm0
|
||||
|
||||
mov eax, dword [rdi + WDI_HEIGHT]
|
||||
mov [rbp - height], eax
|
||||
|
||||
mov eax, dword [rdi + WDI_FIGURE + FIG_TYPE]
|
||||
mov [rbp - fig_type], eax
|
||||
|
||||
mov eax, dword [rdi + WDI_FIGURE + FIG_POSITION]
|
||||
mov [rbp - pos_x], eax
|
||||
|
||||
mov eax, dword [rdi + WDI_FIGURE + FIG_POSITION + 4]
|
||||
mov [rbp - pos_x], eax
|
||||
|
||||
mov eax, dword [rdi + WDI_FIGURE + FIG_VELOCITY]
|
||||
mov [rbp - vel_x], eax
|
||||
|
||||
mov eax, dword [rdi + WDI_FIGURE + FIG_VELOCITY + 4]
|
||||
mov [rbp - vel_y], eax
|
||||
|
||||
mov eax, dword [rdi + WDI_FIGURE + FIG_ANGLE]
|
||||
mov [rbp - angle], eax
|
||||
|
||||
mov eax, dword [rdi + WDI_FIGURE + FIG_ANG_VEL]
|
||||
mov [rbp - angular_vel], eax
|
||||
|
||||
mov eax, dword [rdi + WDI_FIGURE + FIG_SPEED]
|
||||
mov [rbp - speed], eax
|
||||
|
||||
mov eax, dword [rdi + WDI_FIGURE + FIG_RADIUS]
|
||||
mov [rbp - radius], eax
|
||||
|
||||
|
||||
|
||||
|
||||
; Восстановить регистры
|
||||
; Обновить угол: angle += angular_velocity * speed
|
||||
movss xmm0, [rdi + WDI_FIGURE + FIG_ANG_VEL]
|
||||
mulss xmm0, [rdi + WDI_FIGURE + FIG_SPEED]
|
||||
addss xmm0, [rdi + WDI_FIGURE + FIG_ANGLE]
|
||||
movss [rdi + WDI_FIGURE + FIG_ANGLE], xmm0
|
||||
|
||||
leave
|
||||
ret
|
||||
@@ -95,17 +67,177 @@ figure_handle_collision:
|
||||
|
||||
local point_buffer, 128
|
||||
|
||||
; Сохранить регистры
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
|
||||
mov r12, rdi
|
||||
|
||||
; Нормализовать радиус: radius_normalized = radius_pixels / height_pixels
|
||||
movss xmm3, [r12 + WDI_FIGURE + FIG_RADIUS]
|
||||
cvtsi2ss xmm4, dword [r12 + WDI_HEIGHT]
|
||||
divss xmm3, xmm4
|
||||
|
||||
; Вызов place_points_on_circle
|
||||
movss xmm0, [rdi + WDI_FIGURE + FIG_POSITION]
|
||||
movss xmm1, [rdi + WDI_FIGURE + FIG_POSITION + 4]
|
||||
movss xmm0, [r12 + WDI_FIGURE + FIG_POSITION]
|
||||
movss xmm1, [r12 + WDI_FIGURE + FIG_POSITION + 4]
|
||||
movss xmm2, [rel ZERO_CONST] ; смещение угла = 0
|
||||
|
||||
; Установка правильного количества точек
|
||||
mov eax, dword [r12 + WDI_FIGURE + FIG_TYPE]
|
||||
cmp eax, 1 ; FIGURE_TRIANGLE
|
||||
je .figure_triangle
|
||||
cmp eax, 2 ; FIGURE_SQUARE
|
||||
je .figure_square
|
||||
; default (FIGURE_CIRCLE and others): 16 points
|
||||
mov rsi, 16
|
||||
jmp .figure_points_done
|
||||
.figure_triangle:
|
||||
mov rsi, 3
|
||||
jmp .figure_points_done
|
||||
.figure_square:
|
||||
mov rsi, 4
|
||||
mov rdx, 0
|
||||
push rdi
|
||||
mov rdi, rbp
|
||||
add rdi, point_buffer
|
||||
.figure_points_done:
|
||||
|
||||
lea rdi, [rbp + point_buffer]
|
||||
call place_points_on_circle
|
||||
pop rdi
|
||||
|
||||
; Вычислить canvas_width = width_pixels / height_pixels
|
||||
cvtsi2ss xmm0, dword [r12 + WDI_WIDTH]
|
||||
cvtsi2ss xmm1, dword [r12 + WDI_HEIGHT]
|
||||
divss xmm0, xmm1
|
||||
movss xmm14, xmm0 ; сохраняем canvas_width в xmm14
|
||||
movss xmm13, [rel ONE_CONST] ; canvas_height = 1.0 в xmm13
|
||||
|
||||
; Инициализация: r14 = маска коллизий (OR всех точек), r15 = указатель на текущую точку
|
||||
xor r14, r14
|
||||
lea r15, [rbp + point_buffer]
|
||||
mov rcx, rsi
|
||||
|
||||
.point_check:
|
||||
; Загрузить координаты точки
|
||||
movss xmm2, [r15] ; x
|
||||
movss xmm3, [r15 + 4] ; y
|
||||
|
||||
; Вызвать check_collision_mask(canvas_width, canvas_height, x, y)
|
||||
movss xmm0, xmm14 ; width
|
||||
movss xmm1, xmm13 ; height = 1.0
|
||||
push rcx
|
||||
call check_collision_mask
|
||||
pop rcx
|
||||
|
||||
; Объединить маску коллизий
|
||||
or r14, rax
|
||||
|
||||
; Перейти к следующей точке
|
||||
add r15, 8
|
||||
loop .point_check
|
||||
|
||||
; Проверить, были ли коллизии
|
||||
test r14, r14
|
||||
jz .no_collision
|
||||
|
||||
; Обработка коллизий: инвертировать velocity только если движемся к границе
|
||||
|
||||
; Проверка left (bit 0): инвертировать velocity.x только если vel.x < 0
|
||||
test r14, 0x1
|
||||
jz .check_right
|
||||
|
||||
movss xmm0, [r12 + WDI_FIGURE + FIG_VELOCITY]
|
||||
movss xmm1, [rel ZERO_CONST]
|
||||
ucomiss xmm0, xmm1
|
||||
jae .check_right ; если vel.x >= 0, пропускаем
|
||||
|
||||
; vel.x < 0, инвертируем
|
||||
movss xmm1, [rel NEG_ONE_CONST]
|
||||
mulss xmm0, xmm1
|
||||
movss [r12 + WDI_FIGURE + FIG_VELOCITY], xmm0
|
||||
|
||||
.check_right:
|
||||
; Проверка right (bit 2): инвертировать velocity.x только если vel.x > 0
|
||||
test r14, 0x4
|
||||
jz .check_top
|
||||
|
||||
movss xmm0, [r12 + WDI_FIGURE + FIG_VELOCITY]
|
||||
movss xmm1, [rel ZERO_CONST]
|
||||
ucomiss xmm0, xmm1
|
||||
jbe .check_top ; если vel.x <= 0, пропускаем
|
||||
|
||||
; vel.x > 0, инвертируем
|
||||
movss xmm1, [rel NEG_ONE_CONST]
|
||||
mulss xmm0, xmm1
|
||||
movss [r12 + WDI_FIGURE + FIG_VELOCITY], xmm0
|
||||
|
||||
.check_top:
|
||||
; Проверка top (bit 1): инвертировать velocity.y только если vel.y < 0
|
||||
test r14, 0x2
|
||||
jz .check_bottom
|
||||
|
||||
movss xmm0, [r12 + WDI_FIGURE + FIG_VELOCITY + 4]
|
||||
movss xmm1, [rel ZERO_CONST]
|
||||
ucomiss xmm0, xmm1
|
||||
jae .check_bottom ; если vel.y >= 0, пропускаем
|
||||
|
||||
; vel.y < 0, инвертируем
|
||||
movss xmm1, [rel NEG_ONE_CONST]
|
||||
mulss xmm0, xmm1
|
||||
movss [r12 + WDI_FIGURE + FIG_VELOCITY + 4], xmm0
|
||||
|
||||
.check_bottom:
|
||||
; Проверка bottom (bit 3): инвертировать velocity.y только если vel.y > 0
|
||||
test r14, 0x8
|
||||
jz .no_collision
|
||||
|
||||
movss xmm0, [r12 + WDI_FIGURE + FIG_VELOCITY + 4]
|
||||
movss xmm1, [rel ZERO_CONST]
|
||||
ucomiss xmm0, xmm1
|
||||
jbe .no_collision ; если vel.y <= 0, пропускаем
|
||||
|
||||
; vel.y > 0, инвертируем
|
||||
movss xmm1, [rel NEG_ONE_CONST]
|
||||
mulss xmm0, xmm1
|
||||
movss [r12 + WDI_FIGURE + FIG_VELOCITY + 4], xmm0
|
||||
|
||||
.no_collision:
|
||||
; Костыль: если центр фигуры вышел за границу, вернуть его на границу
|
||||
|
||||
; Проверка pos_x < 0
|
||||
movss xmm0, [r12 + WDI_FIGURE + FIG_POSITION]
|
||||
movss xmm1, [rel ZERO_CONST]
|
||||
ucomiss xmm0, xmm1
|
||||
jae .check_pos_x_max
|
||||
movss [r12 + WDI_FIGURE + FIG_POSITION], xmm1 ; pos_x = 0
|
||||
|
||||
.check_pos_x_max:
|
||||
; Проверка pos_x > canvas_width
|
||||
movss xmm0, [r12 + WDI_FIGURE + FIG_POSITION]
|
||||
ucomiss xmm0, xmm14
|
||||
jbe .check_pos_y_min
|
||||
movss [r12 + WDI_FIGURE + FIG_POSITION], xmm14 ; pos_x = canvas_width
|
||||
|
||||
.check_pos_y_min:
|
||||
; Проверка pos_y < 0
|
||||
movss xmm0, [r12 + WDI_FIGURE + FIG_POSITION + 4]
|
||||
movss xmm1, [rel ZERO_CONST]
|
||||
ucomiss xmm0, xmm1
|
||||
jae .check_pos_y_max
|
||||
movss [r12 + WDI_FIGURE + FIG_POSITION + 4], xmm1 ; pos_y = 0
|
||||
|
||||
.check_pos_y_max:
|
||||
; Проверка pos_y > canvas_height (1.0)
|
||||
movss xmm0, [r12 + WDI_FIGURE + FIG_POSITION + 4]
|
||||
ucomiss xmm0, xmm13
|
||||
jbe .position_clamped
|
||||
movss [r12 + WDI_FIGURE + FIG_POSITION + 4], xmm13 ; pos_y = 1.0
|
||||
|
||||
.position_clamped:
|
||||
; Восстановить регистры
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
|
||||
leave
|
||||
ret
|
||||
@@ -135,7 +267,7 @@ place_points_on_circle:
|
||||
|
||||
movss xmm5, [rel ZERO_CONST] ; счётчик
|
||||
mov rcx, rsi
|
||||
.cycle:
|
||||
.loop:
|
||||
movss xmm0, xmm5
|
||||
|
||||
mulss xmm0, xmm4 ; Счётчик*шаг
|
||||
@@ -153,7 +285,7 @@ place_points_on_circle:
|
||||
|
||||
|
||||
addss xmm5, [rel ONE_CONST]
|
||||
loop .cycle
|
||||
loop .loop
|
||||
|
||||
leave
|
||||
ret
|
||||
@@ -189,3 +321,54 @@ sincos_f32_rbp:
|
||||
|
||||
leave ; эквивалент: mov rsp, rbp / pop rbp
|
||||
ret
|
||||
|
||||
|
||||
; Функция проверки выхода за границы с маской
|
||||
; Вход:
|
||||
; xmm0 - width
|
||||
; xmm1 - height
|
||||
; xmm2 - x
|
||||
; xmm3 - y
|
||||
; Выход:
|
||||
; rax - битовая маска границ (left=1, top=2, right=4, bottom=8)
|
||||
check_collision_mask:
|
||||
xor rax, rax ; очистим rax (маска)
|
||||
|
||||
movss xmm4, [rel ZERO_CONST]
|
||||
|
||||
; left: x < 0
|
||||
ucomiss xmm2, xmm4
|
||||
jb .set_left
|
||||
|
||||
.next_left:
|
||||
; right: x > width
|
||||
ucomiss xmm2, xmm0
|
||||
ja .set_right
|
||||
|
||||
.next_right:
|
||||
; top: y < 0
|
||||
ucomiss xmm3, xmm4
|
||||
jb .set_top
|
||||
|
||||
.next_top:
|
||||
; bottom: y > height
|
||||
ucomiss xmm3, xmm1
|
||||
ja .set_bottom
|
||||
|
||||
ret
|
||||
|
||||
.set_left:
|
||||
or rax, 1
|
||||
jmp .next_left
|
||||
|
||||
.set_top:
|
||||
or rax, 2
|
||||
jmp .next_top
|
||||
|
||||
.set_right:
|
||||
or rax, 4
|
||||
jmp .next_right
|
||||
|
||||
.set_bottom:
|
||||
or rax, 8
|
||||
ret
|
||||
|
||||
@@ -16,9 +16,15 @@ void figure_draw(struct window_draw_info* draw_info, float border_thickness, uin
|
||||
|
||||
struct figure_animation_info fig = draw_info->figure;
|
||||
|
||||
/* center in pixels */
|
||||
float cx = fig.position.x * (float)w;
|
||||
float cy = fig.position.y * (float)h;
|
||||
/* Calculate aspect ratio: width is proportional, height is always 1.0 */
|
||||
float aspect_ratio = (float)w / (float)h;
|
||||
|
||||
/* center in pixels:
|
||||
* x coordinates are in range [0, aspect_ratio]
|
||||
* y coordinates are in range [0, 1.0]
|
||||
*/
|
||||
float cx = fig.position.x * (float)h; /* scale x by height to maintain aspect */
|
||||
float cy = fig.position.y * (float)h; /* scale y by height */
|
||||
/* `fig.radius` is in pixels now; use it directly. */
|
||||
float r = fig.radius;
|
||||
float r2 = r * r;
|
||||
|
||||
@@ -69,36 +69,36 @@ static void *window_aux_loop(void *arg)
|
||||
{
|
||||
/* На время обновления позиции фигуры локаем мутекс */
|
||||
pthread_mutex_lock(&draw_info->figure_mutex);
|
||||
// figure_animation_step(draw_info);
|
||||
figure_animation_step(draw_info);
|
||||
|
||||
const size_t n = 8;
|
||||
struct vec2 *pts = malloc(sizeof(struct vec2) * n);
|
||||
if (!pts)
|
||||
{
|
||||
printf("malloc failed\n");
|
||||
}
|
||||
// const size_t n = 8;
|
||||
// struct vec2 *pts = malloc(sizeof(struct vec2) * n);
|
||||
// if (!pts)
|
||||
// {
|
||||
// printf("malloc failed\n");
|
||||
// }
|
||||
|
||||
float center_x = 0.0f;
|
||||
float center_y = 0.0f;
|
||||
float offset = 0.78f;
|
||||
float radius = 1.0f;
|
||||
// float center_x = 0.0f;
|
||||
// float center_y = 0.0f;
|
||||
// float offset = 0.78f;
|
||||
// float radius = 1.0f;
|
||||
|
||||
// Вызов ASM-функции
|
||||
place_points_on_circle(
|
||||
center_x,
|
||||
center_y,
|
||||
offset,
|
||||
radius,
|
||||
(float *)pts, // адрес выходного массива
|
||||
n);
|
||||
// // Вызов ASM-функции
|
||||
// place_points_on_circle(
|
||||
// center_x,
|
||||
// center_y,
|
||||
// offset,
|
||||
// radius,
|
||||
// (float *)pts, // адрес выходного массива
|
||||
// n);
|
||||
|
||||
// Вывод для проверки (и удобной точки останова)
|
||||
for (size_t i = 0; i < n; i++)
|
||||
{
|
||||
printf("%zu: x = %f, y = %f\n", i, pts[i].x, pts[i].y);
|
||||
}
|
||||
// // Вывод для проверки (и удобной точки останова)
|
||||
// for (size_t i = 0; i < n; i++)
|
||||
// {
|
||||
// printf("%zu: x = %f, y = %f\n", i, pts[i].x, pts[i].y);
|
||||
// }
|
||||
|
||||
free(pts);
|
||||
// free(pts);
|
||||
pthread_mutex_unlock(&draw_info->figure_mutex);
|
||||
|
||||
usleep(30 * 1000);
|
||||
|
||||
@@ -105,20 +105,19 @@ static void draw(struct wayland_window *win)
|
||||
// Залочиться, чтобы операции обновления позиции фигуры происходили атомарно
|
||||
pthread_mutex_lock(&draw_info->figure_mutex);
|
||||
struct figure_animation_info figure = draw_info->figure;
|
||||
pthread_mutex_unlock(&draw_info->figure_mutex);
|
||||
|
||||
uint32_t color;
|
||||
switch (figure.type)
|
||||
{
|
||||
case FIGURE_CIRCLE:
|
||||
color = 0xFFFFFFFF;
|
||||
break;
|
||||
case FIGURE_TRIANGLE:
|
||||
color = 0xFFFF0000;
|
||||
break;
|
||||
case FIGURE_SQUARE:
|
||||
case FIGURE_TRIANGLE:
|
||||
color = 0xFF00FF00;
|
||||
break;
|
||||
case FIGURE_SQUARE:
|
||||
color = 0xFF0000FF;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -129,11 +128,13 @@ static void draw(struct wayland_window *win)
|
||||
{
|
||||
uint32_t *row = (uint32_t *)(bytes + y * stride);
|
||||
for (int32_t x = 0; x < (int32_t)draw_info->width; ++x)
|
||||
row[x] = 0xFF000000; /* background black */
|
||||
row[x] = 0xAA5F5F5F; /* background black */
|
||||
}
|
||||
|
||||
/* Draw figure into buffer. border thickness in pixels = 3.0f */
|
||||
figure_draw(&win->draw_info, 3.0f, 0xFFFFFFFF, color);
|
||||
pthread_mutex_unlock(&draw_info->figure_mutex);
|
||||
|
||||
|
||||
wl_surface_attach(win->wl_surface, win->buffer, 0, 0);
|
||||
wl_surface_damage_buffer(win->wl_surface, 0, 0, draw_info->width, draw_info->height);
|
||||
@@ -251,12 +252,12 @@ int window_init(struct wl_display *display, struct wl_event_queue *queue, struct
|
||||
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.velocity.x = 0.5f;
|
||||
draw_info->figure.velocity.y = 0.5f;
|
||||
draw_info->figure.angle = 0.0f;
|
||||
draw_info->figure.angular_velocity = 1.0f; /* radians per second */
|
||||
draw_info->figure.speed = 100.0f; /* pixels per second */
|
||||
draw_info->figure.radius = 20.0f; /* radius in pixels */
|
||||
draw_info->figure.angular_velocity = 1; /* radians per frame */
|
||||
draw_info->figure.speed = 20; /* speed multiplier */
|
||||
draw_info->figure.radius = 25.0f; /* radius in pixels */
|
||||
|
||||
win->buffer = NULL;
|
||||
win->frame_callback = NULL;
|
||||
|
||||
Reference in New Issue
Block a user