// Armature shader (preserve volume skinning) - Optimized Version
struct VertexAttributes {
    float3 position;
    uint normal;
    float4 data1;
    float4 data2;
    float2 data3;
};
struct BlendAttributes {
    float4 weights;
    int4 indicies;
};
struct PoseAttributes {
    float3 S;    // 缩放
    float3 T;    // 偏移
    float4 QR;   // 旋转四元数（实部w在最后）
    float4 QD;   // 对偶四元数
};

// 寄存器绑定保持不变（兼容原有管线）
RWStructuredBuffer<VertexAttributes> rw_buffer : register(u5);
StructuredBuffer<VertexAttributes> base : register(t110);
StructuredBuffer<BlendAttributes> blend : register(t111);
StructuredBuffer<PoseAttributes> pose : register(t112);
Texture1D<float4> IniParams : register(t120);

// 宏定义保持不变（兼容原有参数传递）
#define TIME IniParams[88].x
#define VG_COUNT IniParams[89].x

// 声明仅保留使用到的函数（移除未使用的m_scale）
int i8toi32(uint src);
uint i32toi8(int src);
float3 packed2norm(uint packed);
uint norm2packed(float3 norm, uint ori);

[numthreads(64, 1, 1)]
void main(uint3 threadID : SV_DispatchThreadID)
{
    uint i = threadID.x;
    BlendAttributes b = blend[i]; // 仅读取1次blend数据，减少内存访问
    VertexAttributes v = base[i]; // 仅读取1次base数据，减少内存访问

    // 1. 坐标系统转换 + 类型转换（合并赋值，减少临时变量）
    float4 pos = float4(v.position.x, -v.position.z, v.position.y, 1.0f); // 直接转换轴系，避免二次赋值
    float3 norm = packed2norm(v.normal);
    norm = float3(norm.x, -norm.z, norm.y);
    // 2. 帧插值参数（提前计算，避免重复floor）
    int frame = (int)TIME;
    float inter = frac(TIME); // 替代TIME - floor(TIME)，指令更精简
    float inter_prev = 1.0f - inter;
    int vg_count = (int)VG_COUNT;

    // 3. 计算混合索引（合并计算，减少临时变量）
    int4 idx_prev = frame * vg_count + b.indicies;
    int4 idx_next = (frame + 1) * vg_count + b.indicies;

    // 4. 读取所有需要的pose数据（一次性读取，减少内存访问延迟）
    PoseAttributes p0_prev = pose[idx_prev.x];
    PoseAttributes p1_prev = pose[idx_prev.y];
    PoseAttributes p2_prev = pose[idx_prev.z];
    PoseAttributes p3_prev = pose[idx_prev.w];
    PoseAttributes p0_next = pose[idx_next.x];
    PoseAttributes p1_next = pose[idx_next.y];
    PoseAttributes p2_next = pose[idx_next.z];
    PoseAttributes p3_next = pose[idx_next.w];

    // 5. 线性混合皮肤（LBS）计算 - 缩放+偏移（向量化运算，减少指令数）
    float4 weights = b.weights;
    float3 scale = (p0_prev.S * weights.x + p1_prev.S * weights.y + p2_prev.S * weights.z + p3_prev.S * weights.w) * inter_prev
                 + (p0_next.S * weights.x + p1_next.S * weights.y + p2_next.S * weights.z + p3_next.S * weights.w) * inter;
    float3 bias = (p0_prev.T * weights.x + p1_prev.T * weights.y + p2_prev.T * weights.z + p3_prev.T * weights.w) * inter_prev
                + (p0_next.T * weights.x + p1_next.T * weights.y + p2_next.T * weights.z + p3_next.T * weights.w) * inter;
    pos.xyz = pos.xyz * scale + bias;
    //rw_buffer[i].position = pos.xyz;

    // 6. 对偶四元数混合（DLB）- 移除分支，向量化计算
    float4 qr = p0_prev.QR * weights.x * inter_prev;
    float4 qd = p0_prev.QD * weights.x * inter_prev;

    // 四元数符号修正：用dot结果的符号替代if-else（sign函数返回±1，避免分支）
    float sign1 = sign(dot(p0_prev.QR, p1_prev.QR));
    float sign2 = sign(dot(p0_prev.QR, p2_prev.QR));
    float sign3 = sign(dot(p0_prev.QR, p3_prev.QR));
    float sign0_next = sign(dot(p0_prev.QR, p0_next.QR));
    float sign1_next = sign(dot(p0_prev.QR, p1_next.QR));
    float sign2_next = sign(dot(p0_prev.QR, p2_next.QR));
    float sign3_next = sign(dot(p0_prev.QR, p3_next.QR));

    // 混合所有四元数（向量运算，无分支）
    qr += p1_prev.QR * weights.y * inter_prev * sign1;
    qd += p1_prev.QD * weights.y * inter_prev * sign1;
    qr += p2_prev.QR * weights.z * inter_prev * sign2;
    qd += p2_prev.QD * weights.z * inter_prev * sign2;
    qr += p3_prev.QR * weights.w * inter_prev * sign3;
    qd += p3_prev.QD * weights.w * inter_prev * sign3;
    qr += p0_next.QR * weights.x * inter * sign0_next;
    qd += p0_next.QD * weights.x * inter * sign0_next;
    qr += p1_next.QR * weights.y * inter * sign1_next;
    qd += p1_next.QD * weights.y * inter * sign1_next;
    qr += p2_next.QR * weights.z * inter * sign2_next;
    qd += p2_next.QD * weights.z * inter * sign2_next;
    qr += p3_next.QR * weights.w * inter * sign3_next;
    qd += p3_next.QD * weights.w * inter * sign3_next;

    // 7. 四元数归一化（优化顺序：先算长度，避免重复除法）
    float qr_len = length(qr);
    if (qr_len < 1e-6f) qr_len = 1e-6f; // 避免除零
    qr /= qr_len;
    qd /= qr_len;

    // 8. 构建旋转矩阵（合并计算，减少临时变量trans）
    float qx = qr.x, qy = qr.y, qz = qr.z, qw = qr.w;
    float qdx = qd.x, qdy = qd.y, qdz = qd.z, qdw = qd.w;

    // 旋转矩阵第一列 + 平移分量（对偶四元数展开）
    float m00 = 1.0f - 2.0f*qy*qy - 2.0f*qz*qz;
    float m10 = 2.0f*(qx*qy + qw*qz);
    float m20 = 2.0f*(qx*qz - qw*qy);
    float t0 = 2.0f*(-qdw*qx + qdx*qw - qdy*qz + qdz*qy);

    // 旋转矩阵第二列 + 平移分量
    float m01 = 2.0f*(qx*qy - qw*qz);
    float m11 = 1.0f - 2.0f*qx*qx - 2.0f*qz*qz;
    float m21 = 2.0f*(qy*qz + qw*qx);
    float t1 = 2.0f*(-qdw*qy + qdx*qz + qdy*qw - qdz*qx);

    // 旋转矩阵第三列 + 平移分量
    float m02 = 2.0f*(qx*qz + qw*qy);
    float m12 = 2.0f*(qy*qz - qw*qx);
    float m22 = 1.0f - 2.0f*qx*qx - 2.0f*qy*qy;
    float t2 = 2.0f*(-qdw*qz - qdx*qy + qdy*qx + qdz*qw);

    // 9. 应用变换（直接计算，避免临时float4 trans）
    float3 pos_result;
    pos_result.x = m00*pos.x + m01*pos.y + m02*pos.z + t0*pos.w;
    pos_result.y = m10*pos.x + m11*pos.y + m12*pos.z + t1*pos.w;
    pos_result.z = m20*pos.x + m21*pos.y + m22*pos.z + t2*pos.w;
    float3 norm_result;
    norm_result.x = m00*norm.x + m01*norm.y + m02*norm.z;
    norm_result.y = m10*norm.x + m11*norm.y + m12*norm.z;
    norm_result.z = m20*norm.x + m21*norm.y + m22*norm.z;

    // 11. 还原轴系 + 写入结果（直接赋值，减少临时变量）
    rw_buffer[i].position = float3(pos_result.x, pos_result.z, -pos_result.y);
    rw_buffer[i].normal = norm2packed(float3(norm_result.x, norm_result.z, -norm_result.y), v.normal);


}

// 保留原有辅助函数（未使用但保持兼容）
int i8toi32(uint src) {
    return (src & 0x80) ? (src | 0xffffff80) : (src & 0x7f);
}

uint i32toi8(int src) {
    src = clamp(src, -128, 127); // 替代双if，指令更精简
    return (uint)src & 0xff;
}

float3 packed2norm(uint packed) {
    int x = packed & 0x3ff;
    int y = (packed >> 10) & 0x3ff;
    x = x >= 512 ? x - 1024: x;
    y = y >= 512 ? y - 1024: y;
    float3 norm = float3(float(x)/511, float(y)/511, 0);
    norm.z = 1.0 - abs(norm.x) - abs(norm.y);
    float old_xf = norm.x;
    norm.x = norm.z < 0? (1.0-abs(norm.y))*sign(old_xf): norm.x;
    norm.y = norm.z < 0? (1.0-abs(old_xf))*sign(norm.y): norm.y;
    return normalize(norm);
}

uint norm2packed(float3 norm, uint ori) {
    norm = norm / (abs(norm.x)+abs(norm.y)+abs(norm.z));
    float x_fold = norm.z<0? (1.0-abs(norm.y))*sign(norm.x): norm.x;
    float y_fold = norm.z<0? (1.0-abs(norm.x))*sign(norm.y): norm.y;
    int x_int = clamp(x_fold*511, -511, 511);
    int y_int = clamp(y_fold*511, -511, 511);
    return ori&0xfff00000 | ((y_int&0x3ff) << 10) | (x_int&0x3ff);
}