Размер не зависит от ширины
This commit is contained in:
@@ -13,15 +13,24 @@ enum figure_type
|
|||||||
struct figure_animation_info {
|
struct figure_animation_info {
|
||||||
enum figure_type type;
|
enum figure_type type;
|
||||||
struct vec2 position;
|
struct vec2 position;
|
||||||
|
/* Direction vector; its components are not in pixels. Anim code converts
|
||||||
|
* them to pixel-space and normalizes them so that `speed` is applied as
|
||||||
|
* pixels/sec uniformly in both axes (aspect ratio is accounted for). */
|
||||||
struct vec2 velocity;
|
struct vec2 velocity;
|
||||||
|
|
||||||
float angle;
|
float angle;
|
||||||
float angular_velocity;
|
float angular_velocity;
|
||||||
|
|
||||||
|
/* Speed in pixels per second. This value is applied uniformly to both
|
||||||
|
* axes (X and Y); the animation code converts this pixel speed to
|
||||||
|
* normalized increments for position updates taking window aspect ratio
|
||||||
|
* into account. */
|
||||||
float speed;
|
float speed;
|
||||||
/* Radius of the figure normalized for window width (0..1)
|
/* Radius of the figure in pixels (float)
|
||||||
* This field is used by animation code to check collisions
|
* This field is used by animation code to check collisions
|
||||||
* with the left/right/top/bottom borders. */
|
* with the left/right/top/bottom borders. The animation code
|
||||||
|
* will convert this pixel radius to normalized coordinates for
|
||||||
|
* collision checks against normalized positions. */
|
||||||
float radius;
|
float radius;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -15,25 +15,60 @@ figure_animation_step:
|
|||||||
mov rax, rdi
|
mov rax, rdi
|
||||||
add rax, WDI_FIGURE
|
add rax, WDI_FIGURE
|
||||||
|
|
||||||
; --- compute movement scale: scale = speed * (dt / BASE_SIZE)
|
; --- compute movement increments so that `speed` means pixels/second
|
||||||
|
; Convert velocity to pixel-space (vx = vel.x * width, vy = vel.y * height),
|
||||||
|
; normalize that vector and apply `speed*dt` so movement in pixel units equals speed.
|
||||||
; using SSE for float math
|
; using SSE for float math
|
||||||
movss xmm0, dword [rax + FIG_SPEED] ; xmm0 = speed
|
movss xmm0, dword [rax + FIG_SPEED] ; xmm0 = speed (pixels/sec)
|
||||||
mulss xmm0, [rel SCALE_FACTOR] ; xmm0 = speed * (dt / BASE_SIZE)
|
movss xmm9, [rel DT] ; xmm9 = dt
|
||||||
|
mulss xmm0, xmm9 ; xmm0 = speed * dt (pixels)
|
||||||
|
|
||||||
; dx = velocity.x * scale
|
; load width/height
|
||||||
movss xmm1, dword [rax + FIG_VELOCITY] ; velocity.x
|
mov ebx, dword [rdi + WDI_WIDTH]
|
||||||
mulss xmm1, xmm0
|
cvtsi2ss xmm10, ebx ; xmm10 = width
|
||||||
|
mov ebx, dword [rdi + WDI_HEIGHT]
|
||||||
|
cvtsi2ss xmm11, ebx ; xmm11 = height
|
||||||
|
|
||||||
|
; vx_pixels = vel.x * width
|
||||||
|
movss xmm1, dword [rax + FIG_VELOCITY] ; vel.x
|
||||||
|
mulss xmm1, xmm10 ; xmm1 = vx_pixels
|
||||||
|
|
||||||
|
; vy_pixels = vel.y * height
|
||||||
|
movss xmm2, dword [rax + FIG_VELOCITY + 4]
|
||||||
|
mulss xmm2, xmm11 ; xmm2 = vy_pixels
|
||||||
|
|
||||||
|
; length = sqrt(vx^2 + vy^2)
|
||||||
|
movss xmm3, xmm1
|
||||||
|
mulss xmm3, xmm1 ; xmm3 = vx^2
|
||||||
|
movss xmm4, xmm2
|
||||||
|
mulss xmm4, xmm4 ; xmm4 = vy^2
|
||||||
|
addss xmm3, xmm4 ; xmm3 = vx^2 + vy^2
|
||||||
|
sqrtss xmm3, xmm3 ; xmm3 = length (pixels)
|
||||||
|
|
||||||
|
; if length == 0 -> skip movement
|
||||||
|
ucomiss xmm3, [rel ZERO_CONST]
|
||||||
|
je .skip_move
|
||||||
|
|
||||||
|
; scalar = (speed * dt) / length
|
||||||
|
movss xmm4, xmm0 ; xmm4 = speed*dt
|
||||||
|
divss xmm4, xmm3 ; xmm4 = scalar
|
||||||
|
|
||||||
|
; dx = vel.x * scalar
|
||||||
|
movss xmm1, dword [rax + FIG_VELOCITY]
|
||||||
|
mulss xmm1, xmm4
|
||||||
movss xmm2, dword [rax + FIG_POSITION] ; position.x
|
movss xmm2, dword [rax + FIG_POSITION] ; position.x
|
||||||
addss xmm2, xmm1
|
addss xmm2, xmm1
|
||||||
movss dword [rax + FIG_POSITION], xmm2
|
movss dword [rax + FIG_POSITION], xmm2
|
||||||
|
|
||||||
; dy = velocity.y * scale
|
; dy = vel.y * scalar
|
||||||
movss xmm1, dword [rax + FIG_VELOCITY + 4]
|
movss xmm1, dword [rax + FIG_VELOCITY + 4]
|
||||||
mulss xmm1, xmm0
|
mulss xmm1, xmm4
|
||||||
movss xmm2, dword [rax + FIG_POSITION + 4]
|
movss xmm2, dword [rax + FIG_POSITION + 4]
|
||||||
addss xmm2, xmm1
|
addss xmm2, xmm1
|
||||||
movss dword [rax + FIG_POSITION + 4], xmm2
|
movss dword [rax + FIG_POSITION + 4], xmm2
|
||||||
|
|
||||||
|
.skip_move:
|
||||||
|
|
||||||
; rotate: angle += angular_velocity * dt
|
; rotate: angle += angular_velocity * dt
|
||||||
movss xmm3, dword [rax + FIG_ANG_VEL]
|
movss xmm3, dword [rax + FIG_ANG_VEL]
|
||||||
mulss xmm3, [rel DT]
|
mulss xmm3, [rel DT]
|
||||||
@@ -73,24 +108,30 @@ figure_check_collision_circle:
|
|||||||
|
|
||||||
movss xmm4, dword [rax + FIG_ANG_VEL] ; angvel
|
movss xmm4, dword [rax + FIG_ANG_VEL] ; angvel
|
||||||
|
|
||||||
; radius is stored in figure as normalized relative to window width
|
; radius is stored in figure as pixel count (float)
|
||||||
movss xmm5, dword [rax + FIG_RADIUS]
|
; we keep positions normalized (0..1) so convert radius to normalized
|
||||||
|
; coordinates for x and y: r_x = radius / width, r_y = radius / height
|
||||||
|
movss xmm5, dword [rax + FIG_RADIUS] ; xmm5 = radius_pixels
|
||||||
|
|
||||||
; compute normalized radius for Y: r_y = radius * (width / height)
|
|
||||||
; load width/height from window_draw_info
|
; load width/height from window_draw_info
|
||||||
mov ebx, dword [rdi + WDI_WIDTH]
|
mov ebx, dword [rdi + WDI_WIDTH]
|
||||||
cvtsi2ss xmm10, ebx
|
cvtsi2ss xmm10, ebx ; xmm10 = width
|
||||||
mov ebx, dword [rdi + WDI_HEIGHT]
|
mov ebx, dword [rdi + WDI_HEIGHT]
|
||||||
cvtsi2ss xmm11, ebx
|
cvtsi2ss xmm11, ebx ; xmm11 = height
|
||||||
divss xmm10, xmm11 ; xmm10 = width/height
|
|
||||||
movss xmm12, xmm5
|
|
||||||
mulss xmm12, xmm10 ; xmm12 = radius_y
|
|
||||||
|
|
||||||
; left edge: pos.x < radius ?
|
; compute r_x = radius / width
|
||||||
ucomiss xmm0, xmm5
|
movss xmm12, xmm5
|
||||||
|
divss xmm12, xmm10 ; xmm12 = r_x
|
||||||
|
|
||||||
|
; compute r_y = radius / height
|
||||||
|
movss xmm13, xmm5
|
||||||
|
divss xmm13, xmm11 ; xmm13 = r_y
|
||||||
|
|
||||||
|
; left edge: pos.x < r_x ?
|
||||||
|
ucomiss xmm0, xmm12
|
||||||
jae .check_right
|
jae .check_right
|
||||||
; pos.x = radius
|
; pos.x = radius
|
||||||
movss dword [rax + FIG_POSITION], xmm5
|
movss dword [rax + FIG_POSITION], xmm12
|
||||||
; vel.x = -vel.x
|
; vel.x = -vel.x
|
||||||
movss xmm6, xmm2
|
movss xmm6, xmm2
|
||||||
mulss xmm6, [rel NEG_ONE]
|
mulss xmm6, [rel NEG_ONE]
|
||||||
@@ -104,11 +145,11 @@ figure_check_collision_circle:
|
|||||||
.check_right:
|
.check_right:
|
||||||
; pos.x + radius > 1 ?
|
; pos.x + radius > 1 ?
|
||||||
movss xmm8, [rel ONE_CONST]
|
movss xmm8, [rel ONE_CONST]
|
||||||
addss xmm8, xmm5 ; xmm8 = 1 + radius
|
addss xmm8, xmm12 ; xmm8 = 1 + r_x
|
||||||
; Actually want pos.x + radius > 1 <=> pos.x > 1 - radius
|
; Actually want pos.x + radius > 1 <=> pos.x > 1 - radius
|
||||||
; compute bound = 1 - radius
|
; compute bound = 1 - r_x
|
||||||
movss xmm9, [rel ONE_CONST]
|
movss xmm9, [rel ONE_CONST]
|
||||||
subss xmm9, xmm5
|
subss xmm9, xmm12
|
||||||
ucomiss xmm0, xmm9
|
ucomiss xmm0, xmm9
|
||||||
jbe .done_x
|
jbe .done_x
|
||||||
; pos.x = 1 - radius
|
; pos.x = 1 - radius
|
||||||
@@ -124,10 +165,10 @@ figure_check_collision_circle:
|
|||||||
|
|
||||||
.done_x:
|
.done_x:
|
||||||
; check bottom / top boundaries for y
|
; check bottom / top boundaries for y
|
||||||
; bottom: pos.y < radius
|
; bottom: pos.y < r_y
|
||||||
ucomiss xmm1, xmm12
|
ucomiss xmm1, xmm13
|
||||||
jae .check_top2
|
jae .check_top2
|
||||||
movss dword [rax + FIG_POSITION + 4], xmm12
|
movss dword [rax + FIG_POSITION + 4], xmm13
|
||||||
movss xmm6, xmm3
|
movss xmm6, xmm3
|
||||||
mulss xmm6, [rel NEG_ONE]
|
mulss xmm6, [rel NEG_ONE]
|
||||||
movss dword [rax + FIG_VELOCITY + 4], xmm6
|
movss dword [rax + FIG_VELOCITY + 4], xmm6
|
||||||
@@ -138,9 +179,9 @@ figure_check_collision_circle:
|
|||||||
jmp .done_y
|
jmp .done_y
|
||||||
|
|
||||||
.check_top2:
|
.check_top2:
|
||||||
; top: pos.y > 1 - radius
|
; top: pos.y > 1 - r_y
|
||||||
movss xmm9, [rel ONE_CONST]
|
movss xmm9, [rel ONE_CONST]
|
||||||
subss xmm9, xmm5
|
subss xmm9, xmm13
|
||||||
ucomiss xmm1, xmm9
|
ucomiss xmm1, xmm9
|
||||||
jbe .done_y
|
jbe .done_y
|
||||||
movss dword [rax + FIG_POSITION + 4], xmm9
|
movss dword [rax + FIG_POSITION + 4], xmm9
|
||||||
@@ -156,7 +197,7 @@ figure_check_collision_circle:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
section .rodata
|
section .rodata
|
||||||
SCALE_FACTOR: dd 0.001
|
|
||||||
DT: dd 0.1
|
DT: dd 0.1
|
||||||
NEG_ONE: dd -1.0
|
NEG_ONE: dd -1.0
|
||||||
ONE_CONST: dd 1.0
|
ONE_CONST: dd 1.0
|
||||||
|
ZERO_CONST: dd 0.0
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ void figure_draw(struct window_draw_info* draw_info, float border_thickness, uin
|
|||||||
/* center in pixels */
|
/* center in pixels */
|
||||||
float cx = fig.position.x * (float)w;
|
float cx = fig.position.x * (float)w;
|
||||||
float cy = fig.position.y * (float)h;
|
float cy = fig.position.y * (float)h;
|
||||||
float r = fig.radius * (float)w; /* normalized to width */
|
/* `fig.radius` is in pixels now; use it directly. */
|
||||||
|
float r = fig.radius;
|
||||||
float r2 = r * r;
|
float r2 = r * r;
|
||||||
float border = border_thickness;
|
float border = border_thickness;
|
||||||
if (border < 0.0f) border = 0.0f;
|
if (border < 0.0f) border = 0.0f;
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ static void *window_aux_loop(void *arg)
|
|||||||
figure_animation_step(draw_info);
|
figure_animation_step(draw_info);
|
||||||
pthread_mutex_unlock(&draw_info->figure_mutex);
|
pthread_mutex_unlock(&draw_info->figure_mutex);
|
||||||
|
|
||||||
usleep(100 * 1000);
|
usleep(30 * 1000);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -255,8 +255,8 @@ int window_init(struct wl_display *display, struct wl_event_queue *queue, struct
|
|||||||
draw_info->figure.velocity.y = 0.3f;
|
draw_info->figure.velocity.y = 0.3f;
|
||||||
draw_info->figure.angle = 0.0f;
|
draw_info->figure.angle = 0.0f;
|
||||||
draw_info->figure.angular_velocity = 1.0f; /* radians per second */
|
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.speed = 100.0f; /* pixels per second */
|
||||||
draw_info->figure.radius = 0.05f; /* normalized relative to width: 5% */
|
draw_info->figure.radius = 20.0f; /* radius in pixels */
|
||||||
|
|
||||||
win->buffer = NULL;
|
win->buffer = NULL;
|
||||||
win->frame_callback = NULL;
|
win->frame_callback = NULL;
|
||||||
|
|||||||
Reference in New Issue
Block a user