//====================================================================
// backface_culler.v - 背面剔除器
// 第11课：叉积绕序判断与剔除
//====================================================================
module backface_culler #(
    parameter COORD_WIDTH = 16,
    parameter COLOR_WIDTH = 24
)(
    input  wire                          clk, rst_n,
    input  wire                          prim_valid,
    input  wire signed [COORD_WIDTH-1:0] v0_x, v0_y, v0_z,
    input  wire signed [COORD_WIDTH-1:0] v1_x, v1_y, v1_z,
    input  wire signed [COORD_WIDTH-1:0] v2_x, v2_y, v2_z,
    input  wire [COLOR_WIDTH-1:0]        v0_color, v1_color, v2_color,
    input  wire                          cull_ccw,    // 1=剔除CCW, 0=剔除CW
    output reg                           prim_ready,
    output reg                           pass_valid,  // 通过剔除
    output reg  signed [COORD_WIDTH-1:0] out_v0_x, out_v0_y, out_v0_z,
    output reg  signed [COORD_WIDTH-1:0] out_v1_x, out_v1_y, out_v1_z,
    output reg  signed [COORD_WIDTH-1:0] out_v2_x, out_v2_y, out_v2_z,
    output reg  [COLOR_WIDTH-1:0]        out_v0_color, out_v1_color, out_v2_color,
    output reg                           culled       // 被剔除标志
);
/* verilator lint_off WIDTHEXPAND */
/* verilator lint_off WIDTHTRUNC */
/* verilator lint_off CASEOVERLAP */
/* verilator lint_off CMPCONST */
/* verilator lint_off UNSIGNED */
/* verilator lint_off WIDTHCONCAT */

    reg signed [2*COORD_WIDTH-1:0] cross_z;
    wire is_ccw;
    assign is_ccw = (cross_z > 0);
    always @(*) begin
        cross_z = (v1_x - v0_x) * (v2_y - v0_y) - (v1_y - v0_y) * (v2_x - v0_x);
    end
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin prim_ready<=1; pass_valid<=0; culled<=0; end
        else begin
            pass_valid <= 0; culled <= 0;
            if (prim_valid) begin
                if ((cull_ccw && is_ccw) || (!cull_ccw && !is_ccw)) begin
                    culled <= 1; // 被剔除
                end else begin
                    out_v0_x<=v0_x; out_v0_y<=v0_y; out_v0_z<=v0_z;
                    out_v1_x<=v1_x; out_v1_y<=v1_y; out_v1_z<=v1_z;
                    out_v2_x<=v2_x; out_v2_y<=v2_y; out_v2_z<=v2_z;
                    out_v0_color<=v0_color; out_v1_color<=v1_color; out_v2_color<=v2_color;
                    pass_valid <= 1;
                end
            end
        end
    end
endmodule