光栅渲染器(七)线框模型绘制和背部剔除实现

我们曾经完成过按多边形顶点输入完成无填充多边形顶点的绘制,所以现在可以按同样的思路绘制线框模型

设置状态

 enum _State {
     normal,
     wireframe
 };
 _State _state = normal;

我们利用这个状态改变模型是之前渲染出的彩色模型还是线框模型

设置状态改变条件

我们选择用space按键改变当前模型的状态

//************************键盘输入*******************
void myKeyBoard(unsigned char theKey, int MouseX, int MouseY)
{
    switch (theKey)
    {
    case 'w':
        CameraPos -= 0.1;
        myDisplay();
        break;
    case 's':
        CameraPos += 0.1;
        myDisplay();
        break;
    case 'a':
        Alpha += 0.1;
        myDisplay();
        break;
    case 'd':
        Alpha -= 0.1;
        myDisplay();
        break;
    case ' ':
        switch (_state)
        {
            case normal:
                _state = wireframe;
                myDisplay();
                break;
            case wireframe:
                _state = normal;
                myDisplay();
                break;
            default:
                break;
        }
        break;
    default:
        break;
    }
}

更改之前的画面函数

void draw_plane( int a, int b, int c, int d) {
    vertex_t p1 = mesh[a], p2 = mesh[b], p3 = mesh[c], p4 = mesh[d];
    vector<vertex_t> vs{ p1,p2,p3,p4 };

    switch (_state)
    {
        case normal:
            DrawTriangle(p1, p2, p3);
            DrawTriangle(p3, p4, p1);
            break;
        case wireframe:
            DrawTriangle_wire(vs);
            break;
        default:
            break;
    }

}

绘制线框模型

//绘制线框多边形
void DrawTriangle_wire(vector<vertex_t> vs)
{
    int size = vs.size();
    vector<vertex_t> ps;
    for (int i = 0; i < size; i++)
    {
        vertex_t vss=vs[i];
        point_t c, v;
        point_t p = vs[i].pos;
        transform_apply(&Transform, &c, &p);
        if (transform_check_cvv(&c) != 0) return;
        transform_homogenize(&Transform, &v, &c);
        vss.pos = v;
        vss.pos.w = c.w;
        vss.color.r = 1;
        vss.color.g = 1;
        vss.color.b = 1;
        vss.color.a = 1;
        ps.push_back(vss);
    }
    for (int i = 0; i < size; i++)
    {
        if(i+1<=size-1)
            DrawLine(ps[i], ps[i+1]);
        else
            DrawLine(ps[i], ps[0]);
    }

}

这里写图片描述
由于没有加入背部剔除,所以我们视野内有多余的线段

背部剔除

只要规定好画正方体时顶点数据的输入顺序,利用方向叉乘和点积判断
这里写图片描述
我们所见的面点的顺序应为顺时针,不能见到的为逆时针
所有修改的顶点顺序为如下

vertex_t mesh[8] = {
    { { 1, -1,  1, 1 },{ 1.0f, 0.2f, 0.2f } },
    { { -1, -1,  1, 1 },{ 0.2f, 1.0f, 0.2f } },
    { { -1,  1,  1, 1 },{ 0.2f, 0.2f, 1.0f }},
    { { 1,  1,  1, 1 },{ 1.0f, 0.2f, 1.0f } },
    { { 1, -1, -1, 1 },{ 1.0f, 1.0f, 0.2f } },
    { { -1, -1, -1, 1 },{ 0.2f, 1.0f, 1.0f } },
    { { -1,  1, -1, 1 },{ 1.0f, 0.3f, 0.3f }},
    { { 1,  1, -1, 1 },{ 0.2f, 1.0f, 0.3f } },
};
//************************画立方体*******************
void DrawBox()
{
    matrix_t m;
    //matrix_set_rotate(&m, -1,1, 1, Alpha);
    matrix_set_rotate(&m, -1, -1, 1, Alpha);
    Transform.world = m;
    transform_update(&Transform);

    draw_plane( 0, 1, 2, 3);
    draw_plane(4, 7, 6, 5);
    draw_plane( 0, 4, 5, 1);
    draw_plane( 1, 5, 6, 2);
    draw_plane(2, 6, 7, 3);
    draw_plane( 3, 7, 4, 0);
}

接下来是背部剔除的代码

// 背部剔除
bool DeleteBack(vertex_t ve1, vertex_t ve2, vertex_t ve3)
{
    vector_t direction = {0,0,-1,1}//视角所见的方向矢量
;
    vector_t normal;//法线
    vector_t v1, v2;
    vector_sub(&v1,&ve2.pos, &ve1.pos);
    vector_sub(&v2, &ve3.pos, &ve2.pos);
    v1.z = 0;
    v2.z = 0;
    vector_crossproduct(&normal, &v1, &v2);
    float dot = vector_dotproduct(&normal, &direction);
    if (dot<0) return true;
    return false;
} 

利用叉乘获得面的方向,通过点积正负判断法线的方向,从而得知面顶点的方向
修改的绘制线框模型的代码如下

//绘制线框多边形
void DrawTriangle_wire(vector<vertex_t> vs)
{

    int size = vs.size();
    vector<vertex_t> ps;
    for (int i = 0; i < size; i++)
    {
        vertex_t vss=vs[i];
        point_t c, v;
        point_t p = vs[i].pos;

        transform_apply(&Transform, &c, &p);
        if (transform_check_cvv(&c) != 0) return;
        transform_homogenize(&Transform, &v, &c);
        vss.pos = v;
        vss.pos.w = c.w;
        vss.color.r = 1;
        vss.color.g = 1;
        vss.color.b = 1;
        vss.color.a = 1;
        ps.push_back(vss);

    }
    if (DeleteBack(ps[0], ps[1], ps[2])) return;

    for (int i = 0; i < size; i++)
    {
        if (i + 1 <= size - 1)
        {

            DrawLine(ps[i], ps[i + 1]);
        }       
        else if(i == size - 1)
        {

            DrawLine(ps[i], ps[0]);
        }

    }


}

这里写图片描述
完成

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值