feat: major engine overhaul - scene demo with lighting, sphere, ground

- Scene Demo: cube + sphere + ground plane with proper lighting
- Audio: XAudio2 dynamic loading + WAV playback
- Physics: expanded collision system
- Renderer: improved pipeline with materials
- UI: extended widget system
- VisualScript: enhanced serializer + block interactions
- ASM: optimized math/memory/profiling routines
- Window: mouse input + scroll support
This commit is contained in:
shuiyu1123 committed 2026-07-12 08:21:07 +08:00
1 parent 2653926d85
commit 0669d102ce
35 files changed
+1844 -314

No files matched your search

+10
View File
@@ -125,3 +125,13 @@ externdef fast_strcmp:PROC
externdef prof_rdtsc:PROC
externdef prof_cycles_to_ms:PROC
externdef prof_get_freq:PROC
; C 数学运行时
externdef cosf:PROC
externdef sinf:PROC
externdef tanf:PROC
; Windows API
externdef Sleep:PROC
externdef QueryPerformanceFrequency:PROC
externdef QueryPerformanceCounter:PROC
+79 -40
View File
@@ -514,9 +514,13 @@ mat4_scale_f ENDP
mat4_rotate_x PROC
; cos(angle), sin(angle)
movss xmm0, dword ptr [rcx] ; angle
movss xmm1, xmm0
cosss xmm0 ; cos
sinss xmm1 ; sin
movss xmm1, xmm0 ; save angle
call cosf ; xmm0 = cos
movss xmm2, xmm0 ; save cos
movss xmm0, xmm1 ; restore angle
call sinf ; xmm0 = sin
movss xmm1, xmm0 ; xmm1 = sin
movss xmm0, xmm2 ; xmm0 = cos
mov rax, rdx ; out
movss dword ptr [rax], 3F800000h ; m[0][0] = 1.0
@@ -550,9 +554,13 @@ mat4_rotate_x ENDP
; void mat4_rotate_y(float angle, Mat4* out)
mat4_rotate_y PROC
movss xmm0, dword ptr [rcx]
movss xmm1, xmm0
cosss xmm0
sinss xmm1
movss xmm1, xmm0 ; save angle
call cosf ; xmm0 = cos
movss xmm2, xmm0 ; save cos
movss xmm0, xmm1 ; restore angle
call sinf ; xmm0 = sin
movss xmm1, xmm0 ; xmm1 = sin
movss xmm0, xmm2 ; xmm0 = cos
mov rax, rdx
movss dword ptr [rax], xmm0 ; m[0][0] = cos
@@ -583,9 +591,13 @@ mat4_rotate_y ENDP
; void mat4_rotate_z(float angle, Mat4* out)
mat4_rotate_z PROC
movss xmm0, dword ptr [rcx]
movss xmm1, xmm0
cosss xmm0
sinss xmm1
movss xmm1, xmm0 ; save angle
call cosf ; xmm0 = cos
movss xmm2, xmm0 ; save cos
movss xmm0, xmm1 ; restore angle
call sinf ; xmm0 = sin
movss xmm1, xmm0 ; xmm1 = sin
movss xmm0, xmm2 ; xmm0 = cos
mov rax, rdx
movss dword ptr [rax], xmm0 ; m[0][0] = cos
@@ -621,7 +633,9 @@ mat4_perspective PROC
; tan(fovY/2)
movss xmm4, xmm0
mulss xmm4, dword ptr [_half] ; fovY/2
tanss xmm4, xmm4 ; tan(fovY/2)
movss xmm0, xmm4
call tanf
movss xmm4, xmm0 ; xmm4 = tan(fovY/2)
; 1 / (aspect * tan)
movss xmm5, xmm1
@@ -970,7 +984,8 @@ quat_slerp PROC
subss xmm1, dword ptr [rdx]
movss dword ptr [rsp - 16], xmm1
; ... (需要保存到临时空间)
negss xmm0 ; dot = -dot
movss xmm1, dword ptr [_negate_mask] ; 0x80000000
xorps xmm0, xmm1 ; dot = -dot
slerp_no_flip:
; 简化: 线性插值 + 归一化
@@ -1040,7 +1055,10 @@ quat_from_axis_angle PROC
mulss xmm0, dword ptr [_half] ; halfAngle
; s = sin(halfAngle)
sinss xmm1, xmm0
movss xmm2, xmm0 ; save halfAngle
call sinf
movss xmm1, xmm0 ; xmm1 = sin
movss xmm0, xmm2 ; restore halfAngle
; 归一化轴
movss xmm2, dword ptr [rcx]
@@ -1074,9 +1092,7 @@ quat_from_axis_angle PROC
movss dword ptr [r8 + 8], xmm0
; out.w = cos(halfAngle)
movss xmm0, dword ptr [rdx]
mulss xmm0, dword ptr [_half]
cosss xmm0, xmm0
call cosf
movss dword ptr [r8 + 12], xmm0
ret
@@ -1090,21 +1106,42 @@ quat_from_euler PROC
mulss xmm1, dword ptr [_half] ; yaw/2
mulss xmm2, dword ptr [_half] ; roll/2
; cos/sin
cosss xmm3, xmm0 ; cp
sinss xmm4, xmm0 ; sp
cosss xmm5, xmm1 ; cy
sinss xmm6, xmm1 ; sy
cosss xmm7, xmm2 ; cr
; sr 需要额外寄存器
sub rsp, 8
sinss xmm0, xmm2 ; sr
movss dword ptr [rsp], xmm0
; 保存半角并计算 cos/sin
sub rsp, 48
movss dword ptr [rsp + 0], xmm0 ; pitch/2
movss dword ptr [rsp + 4], xmm1 ; yaw/2
movss dword ptr [rsp + 8], xmm2 ; roll/2
call cosf
movss dword ptr [rsp + 12], xmm0 ; cp
movss xmm0, dword ptr [rsp + 0]
call sinf
movss dword ptr [rsp + 16], xmm0 ; sp
movss xmm0, dword ptr [rsp + 4]
call cosf
movss dword ptr [rsp + 20], xmm0 ; cy
movss xmm0, dword ptr [rsp + 4]
call sinf
movss dword ptr [rsp + 24], xmm0 ; sy
movss xmm0, dword ptr [rsp + 8]
call cosf
movss dword ptr [rsp + 28], xmm0 ; cr
movss xmm0, dword ptr [rsp + 8]
call sinf
movss dword ptr [rsp + 32], xmm0 ; sr
movss xmm3, dword ptr [rsp + 12] ; cp
movss xmm4, dword ptr [rsp + 16] ; sp
movss xmm5, dword ptr [rsp + 20] ; cy
movss xmm6, dword ptr [rsp + 24] ; sy
movss xmm7, dword ptr [rsp + 28] ; cr
movss xmm2, dword ptr [rsp + 32] ; xmm2 = sr
add rsp, 48
; out.x = sr*cp*cy - cr*sp*sy
movss xmm0, xmm7 ; cr... 需要重新组织
; 简化: 使用栈
movss xmm0, dword ptr [rsp] ; sr
movss xmm0, xmm2 ; sr
mulss xmm0, xmm3 ; sr*cp
mulss xmm0, xmm5 ; sr*cp*cy
movss xmm1, xmm7 ; cr
@@ -1117,9 +1154,10 @@ quat_from_euler PROC
movss xmm0, xmm7
mulss xmm0, xmm4
mulss xmm0, xmm5
movss xmm1, dword ptr [rsp]
mulss xmm1, xmm3
mulss xmm1, xmm6
movss xmm1, xmm0 ; cr*sp*cy
movss xmm0, xmm2 ; sr (saved above in xmm2)
mulss xmm0, xmm3
mulss xmm0, xmm6
addss xmm0, xmm1
movss dword ptr [rcx + 4], xmm0
@@ -1127,23 +1165,24 @@ quat_from_euler PROC
movss xmm0, xmm7
mulss xmm0, xmm3
mulss xmm0, xmm6
movss xmm1, dword ptr [rsp]
mulss xmm1, xmm4
mulss xmm1, xmm5
subss xmm0, xmm1
movss dword ptr [rcx + 8], xmm0
movss xmm1, xmm0 ; cr*cp*sy
movss xmm0, xmm2 ; sr
mulss xmm0, xmm4
mulss xmm0, xmm5
subss xmm1, xmm0
movss dword ptr [rcx + 8], xmm1
; out.w = cr*cp*cy + sr*sp*sy
movss xmm0, xmm7
mulss xmm0, xmm3
mulss xmm0, xmm5
movss xmm1, dword ptr [rsp]
mulss xmm1, xmm4
mulss xmm1, xmm6
movss xmm1, xmm0 ; cr*cp*cy
movss xmm0, xmm2 ; sr
mulss xmm0, xmm4
mulss xmm0, xmm6
addss xmm0, xmm1
movss dword ptr [rcx + 12], xmm0
add rsp, 8
ret
quat_from_euler ENDP
+25 -1
View File
@@ -5,7 +5,7 @@
#include <stdlib.h>
#include <Windows.h>
#ifndef MATH_ASM_AVAILABLE
#if !defined(MATH_ASM_AVAILABLE) || MATH_ASM_AVAILABLE == 0
typedef struct { float x, y, z; } Vec3;
typedef struct { float x, y, z, w; } Vec4;
@@ -37,6 +37,30 @@ static inline void quat_normalize(const Quat* q, Quat* o) { float l=sqrtf(q->x*q
static inline void quat_rotate_vec3(const Quat* q, const Vec3* v, Vec3* o) { Quat vq={v->x,v->y,v->z,0}; Quat qinv; quat_conjugate_raw(q,&qinv); Quat tmp; quat_multiply(q,&vq,&tmp); Quat result; quat_multiply(&tmp,&qinv,&result); o->x=result.x; o->y=result.y; o->z=result.z; }
static inline void quat_to_matrix(const Quat* q, Mat4* o) { float xx=q->x*q->x,yy=q->y*q->y,zz=q->z*q->z,xy=q->x*q->y,xz=q->x*q->z,yz=q->y*q->z,wx=q->w*q->x,wy=q->w*q->y,wz=q->w*q->z; mat4_identity(o); o->m[0][0]=1-2*(yy+zz); o->m[0][1]=2*(xy+wz); o->m[0][2]=2*(xz-wy); o->m[1][0]=2*(xy-wz); o->m[1][1]=1-2*(xx+zz); o->m[1][2]=2*(yz+wx); o->m[2][0]=2*(xz+wy); o->m[2][1]=2*(yz-wx); o->m[2][2]=1-2*(xx+yy); }
static inline void quat_from_euler(float x, float y, float z, Quat* o) {
float cx = cosf(x * 0.5f), sx = sinf(x * 0.5f);
float cy = cosf(y * 0.5f), sy = sinf(y * 0.5f);
float cz = cosf(z * 0.5f), sz = sinf(z * 0.5f);
o->w = cx * cy * cz + sx * sy * sz;
o->x = sx * cy * cz - cx * sy * sz;
o->y = cx * sy * cz + sx * cy * sz;
o->z = cx * cy * sz - sx * sy * cz;
}
static inline void quat_to_euler(const Quat* q, float* x, float* y, float* z) {
float sinr_cosp = 2.0f * (q->w * q->x + q->y * q->z);
float cosr_cosp = 1.0f - 2.0f * (q->x * q->x + q->y * q->y);
*x = atan2f(sinr_cosp, cosr_cosp);
float sinp = 2.0f * (q->w * q->y - q->z * q->x);
if (fabsf(sinp) >= 1.0f) *y = copysignf(1.57079633f, sinp);
else *y = asinf(sinp);
float siny_cosp = 2.0f * (q->w * q->z + q->x * q->y);
float cosy_cosp = 1.0f - 2.0f * (q->y * q->y + q->z * q->z);
*z = atan2f(siny_cosp, cosy_cosp);
}
static inline void* mem_aligned_alloc(uint64_t size, uint64_t alignment) { void* p; p = _aligned_malloc(size, alignment); return p; }
static inline void mem_aligned_free(void* ptr) { _aligned_free(ptr); }
+17 -14
View File
@@ -114,7 +114,7 @@ mem_aligned_realloc PROC
push rdi
push rsi
push r12
sub rsp, 40
sub rsp, 56 ; shadow + 3 saved qwords
mov rbx, rdx ; rbx = new size
mov rdi, r8 ; rdi = alignment
@@ -124,8 +124,11 @@ mem_aligned_realloc PROC
jz realloc_alloc
; 保存旧信息
mov rsi, [rcx - 8] ; 原始指针
mov r12, [rcx - 16] ; 旧 size
mov [rsp + 32], rcx ; 旧对齐指针(即用户数据起始)
mov rax, [rcx - 8]
mov [rsp + 24], rax ; 旧原始 malloc 指针
mov rax, [rcx - 16]
mov [rsp + 16], rax ; 旧 size
; 分配新内存
mov rcx, rbx
@@ -134,26 +137,26 @@ mem_aligned_realloc PROC
test rax, rax
jz realloc_failed
mov rsi, rax ; rsi = 新对齐指针
; 复制旧数据 (取较小值)
mov rdx, r12
mov rdx, [rsp + 16] ; 旧 size
cmp rdx, rbx
jbe realloc_copy_ok
mov rdx, rbx
realloc_copy_ok:
mov rdi, rax ; 保存新指针
mov rcx, rax ; dst
; rsi = 旧数据起始
mov rsi, [rcx - 8] ; 旧原始指针
; 需要获取旧的对齐偏移
; 简化: 直接复制
; fast_memcpy(dst, src, count): rcx=dst, rdx=src, r8=count
mov rcx, rsi
mov r8, rdx
mov rdx, [rsp + 32] ; 旧对齐指针
call fast_memcpy
; 释放旧内存
mov rcx, rsi
; 释放旧内存(使用原始 malloc 指针)
mov rcx, [rsp + 24]
call mem_aligned_free
mov rax, rdi ; 返回新指针
mov rax, rsi ; 返回新指针
jmp realloc_done
realloc_alloc:
@@ -166,7 +169,7 @@ realloc_failed:
xor rax, rax
realloc_done:
add rsp, 40
add rsp, 56
pop r12
pop rsi
pop rdi
+25 -49
View File
@@ -28,14 +28,12 @@ prof_rdtsc PROC
prof_rdtsc ENDP
; uint64_t prof_get_freq(void) -> RAX
; 获取 CPU 频率 (通过 OS 或推断)
; 获取 CPU 频率 (Hz), 使用 QPC 校准 TSC
prof_get_freq PROC
; 检查是否已初始化
cmp byte ptr [cpu_freq_init], 0
jnz prof_freq_return
; 初始化 CPU 频率
; 方法: 使用 QueryPerformanceCounter 测量 RDTSC
push rbx
push rdi
push rsi
@@ -46,7 +44,7 @@ prof_get_freq PROC
call QueryPerformanceFrequency
; 获取起始 QPC 和 TSC
lea rcx, [rsp + 16]
lea rcx, [rsp + 24]
call QueryPerformanceCounter
rdtscp
shl rdx, 32
@@ -54,37 +52,31 @@ prof_get_freq PROC
mov rbx, rax ; rbx = 起始 TSC
; 等待约 10ms
mov rcx, 10000 ; 10,000 微秒
mov rcx, 10 ; 10 毫秒
call Sleep
; 获取结束 QPC 和 TSC
lea rcx, [rsp]
lea rcx, [rsp + 16]
call QueryPerformanceCounter
rdtscp
shl rdx, 32
or rax, rdx
mov rdi, rax ; rdi = 结束 TSC
; 计算经过的 QPC ticks
mov rax, [rsp]
sub rax, [rsp + 16] ; qpc_diff
; qpc_diff = end_qpc - start_qpc
mov rax, [rsp + 16]
sub rax, [rsp + 24]
mov rsi, rax ; rsi = qpc_diff
; 计算 QPC 频率 (ticks/sec)
mov rsi, [rsp + 32]
; tsc_diff = end_tsc - start_tsc
mov rcx, rdi
sub rcx, rbx ; rcx = tsc_diff
; TSC diff
mov rax, rdi
sub rax, rbx ; tsc_diff
; CPU freq = tsc_diff * qpc_freq / qpc_diff
; 但 qpc_diff 对应 10ms, 所以要 * 100
mov rdx, rsi
mul rdx ; tsc_diff * qpc_freq
; rdx:rax = result
div qword ptr [rsp + 16] ; / qpc_diff
; rax = freq * 100 (因为等待了 10ms)
mov rcx, 100
mul rcx
; cpu_freq = tsc_diff * qpc_freq / qpc_diff
mov rax, rcx ; rax = tsc_diff
mov rdx, [rsp + 32] ; rdx = qpc_freq
mul rdx ; rdx:rax = tsc_diff * qpc_freq
div rsi ; rax = freq (Hz)
mov [cpu_freq], rax
mov byte ptr [cpu_freq_init], 1
@@ -100,33 +92,17 @@ prof_freq_return:
prof_get_freq ENDP
; double prof_cycles_to_ms(uint64_t cycles) -> XMM0
; 将 TSC cycles 转换为毫秒
; 将 TSC cycles 转换为毫秒: ms = cycles * 1000 / freq
prof_cycles_to_ms PROC
; 先获取频率
call prof_get_freq
; rax = CPU freq (Hz)
mov rdx, rcx ; 保存 cycles
call prof_get_freq ; rax = CPU freq (Hz)
; ms = cycles / (freq / 1000)
; 或: ms = cycles * 1000 / freq
mov rdx, 1000
mul rdx ; freq * 1000
; rdx:rax = freq * 1000
; 转换为 double
cvtsi2sd xmm0, qword ptr [rsp - 8] ; 需要栈存储
; 简化: 使用整数除法再转 double
mov rcx, rax
mov rax, [cpu_freq]
; 重新计算
mov rax, rcx
; cycles * 1000 / freq
; 已经: rax = freq * 1000, 需要 cycles * 1000 / freq
; 调整: cycles * 1000 / freq = cycles / (freq/1000)
; 简化实现
cvtsi2sd xmm0, rcx ; cycles * 1000 (转 double)
cvtsi2sd xmm1, rax ; freq (转 double)
divsd xmm0, xmm1 ; (cycles*1000) / freq = ms
cvtsi2sd xmm0, rdx ; xmm0 = cycles (double)
mov rcx, 1000
cvtsi2sd xmm1, rcx ; xmm1 = 1000.0
mulsd xmm0, xmm1 ; cycles * 1000
cvtsi2sd xmm1, rax ; xmm1 = freq
divsd xmm0, xmm1 ; ms
ret
prof_cycles_to_ms ENDP
+6 -27
View File
@@ -255,42 +255,21 @@ fast_memset ENDP
; uint64_t fast_strlen(const char* str) -> RAX
; 使用 SSE4.2 PCMPESTRI 搜索 null terminator
fast_strlen PROC
mov rax, rcx ; rax = str
xor rcx, rcx ; rcx = 计数器
; 每次检查 16 字节
mov rdx, rcx ; rdx = original str
pxor xmm0, xmm0 ; 搜索 0
strlen_sse_loop:
; 检查是否接近字符串末尾 (避免越界读取)
; 简化: 逐 16 字节检查
movdqu xmm1, xmmword ptr [rax + rcx]
pcmpestrm xmm0, xmm1, 00001000b ; 搜索 0, 返回掩码
mov rax, rcx ; rax = 当前 16 字节块起始
movdqu xmm1, xmmword ptr [rcx]
pcmpestri xmm0, xmm1, 00001000b ; 搜索 0, CF=1 表示找到, ECX=偏移
jc strlen_found
add rcx, 16
jmp strlen_sse_loop
strlen_found:
; 获取第一个匹配位置
pcmpestri xmm0, xmm1, 00001000b ; ECX = 匹配位置
; rax = 块起始, rcx (ecx) = 块内偏移
add rax, rcx
add rax, rcx
; 需要计算实际位置
; 简化: 使用标量回退
mov rax, rcx
ret
; 标量回退
strlen_scalar:
mov rax, rcx
strlen_scalar_loop:
cmp byte ptr [rax], 0
je strlen_scalar_done
inc rax
jmp strlen_scalar_loop
strlen_scalar_done:
sub rax, rcx
sub rax, rdx
ret
fast_strlen ENDP