当前位置:首页 > 未分类 > 正文内容

实验一:OpenGL的Bresenham画线算法实现

haohao5年前 (2020-11-29)未分类602
#include "stdafx.h"

#include <gl/GLUT.h>
#include <iostream>

using namespace std;

float wid = 400;         //设置窗口的大小,约定窗口必须为正方形
float height = wid;      //设置窗口的大小
int numbers = 20;       //设置划分的网格的个数
float t = wid/numbers; //模拟像素下的单位1
/*
 参数设置说明:
 输入直线的两点A(x1,y1);B(x2,y2)
 您应当确保参数范围在-400~400.且为整数。
 *支持不同斜率
 *支持两点位置颠倒
 */
int x1 = -321,y1=-432,x2 =210,y2 = 456;
void draw_point(float x, float y,int k_kind,int d_kind);
float translater(int x);

void swap(int &a, int &b)
{   int tmp = 0;
    tmp = b;
    b = a;
    a = tmp;  
}

void bresenham(int x1, int y1,int x2, int y2){
    /*
     函数说明:bresenham算法部分
     参数说明:与openGL已有的划线函数一样,要求用户提供的是点的起点(x1,y1)和终点(x2,y2)
     为了便于观察,我们会绘制原像素下的直线。
     这里的坐标要求是-1 ~ 1
     */
    int k_kind = 0; //k_kind用来表示斜率的类型。0是0~1;1是1~无穷;2是0~-1;3是负无穷~-1
    int d_kind =0; //d_kind用来表示dy正负的类型。
    if (x1 > x2) {
        swap(x1,x2);
        swap(y1,y2);
    }
    int dx = abs(x2-x1), dy = abs(y2-y1);
    if (y1 > y2) {//如果是向下的
        y1 = -y1;
        y2 = -y2;
        d_kind = 1;
    }
    if (dy > dx) { //斜率介于1~无穷的,将看作坐标系变换(这里将坐标变换)。
        swap(x1, y1);
        swap(x2,y2);
        swap(dx,dy);
        k_kind = 1;
    }
    float d  = (dy +dy -dx)*t;     //令d为决策量(这里利用d = dx*w*2避免浮点运算)
    float x = x1+0.0,y = y1+0.0;
    draw_point(translater(x),translater(y),k_kind,d_kind); //绘制下一个点
    while( x < x2){             //以x为步长
        if (d < 0){
            d += 2*dy*t;
        }
        else{
            d += 2*(dy-dx)*t;
            y += t;    //说明应该画在上面那个位置
        }
        x= x  +  t;
        draw_point(translater(x),translater(y),k_kind,d_kind); //绘制下一个点
    }
}

float translater(int x){
    /*
     函数说明:将像素坐标下的坐标转化为openGL坐标
     参数说明:传入点像素坐标-wid-wid,返回-1~1坐标
     */
    return  x/wid;
}

void draw_point(float x , float y, int k_kind,int d_kind){
    /*
     函数说明:绘制像素的点,这里将点的大小设置为7。
     颜色采用蓝色。
     参数说明:浮点数x,y是openGl坐标系。kind是指明斜率的类型
    */
    glPointSize(7);
    glColor3f(0.0,0.0,1.0);
    glBegin(GL_POINTS);
    //cout <<"k:"<<k_kind<<"d:" << d_kind  << endl;
    if(k_kind==0&&d_kind==1){
        y = -y;
    }else if (k_kind ==1 &&d_kind==1){
        x= -x;
        swap(x,y);
    }else if (k_kind==1&&d_kind ==0){
        swap(x,y);
    }
    glVertex3f(x,y,0.0);
    glEnd();
    glFlush();
}

void grid(){
    /*
     函数说明:绘制网格为了便于将真实的像素pixel转化为我们模拟的像素
     */
    glClearColor(0, 0, 0, 0);//这是设置背景色,必须要在glclear之前调用
    glClear(GL_COLOR_BUFFER_BIT);
    //画直线
    int wid_number = numbers;
    int hei_number = numbers;
    float delta_wid = wid / wid_number;
    float delta_hei = height / hei_number;
    glColor3f(1.0,1.0,0);
    for (int i = 1; i < 40 ; i ++ ) {
        glBegin(GL_LINES);
        glVertex2f(-1+i*delta_hei/height, -1);
        glVertex2f(-1+i*delta_hei/height, 1);
        glVertex2f(-1,-1+i*delta_hei/height);
        glVertex2f(1,-1+i*delta_hei/height);
        glEnd();
        glFlush();
    }
    glColor3f(1.0,0,0);
    glBegin(GL_LINES);   //绘制坐标系,便于观察
    glVertex2f(-1,0);
    glVertex2f(1,0);
    glVertex2f(0,-1);
    glVertex2f(0,1);
    glEnd();
    glFlush();
    glBegin(GL_LINES);
    glColor3f(1.0,0.0,0.0);
    glVertex2f(translater(x1),translater(y1)); //定点坐标范围
    glVertex2f(translater(x2),translater(y2));
    glEnd();
    glFlush();
    //刷新缓冲,保证绘图命令能被执行
    bresenham(x1, y1,x2,y2);
}

int main(int argc, char *argv[]) {
    //初始化GLUT library
    glutInit(&argc, argv);
    //对窗口的大小进行初始化
    glutInitWindowSize(700,700);
    glutInitWindowPosition(300,200);
    // 设置窗口出现的位置
    //glutInitWindowPosition(int x, int y);
    glutInitDisplayMode(GLUT_RGBA);
    glutCreateWindow("class16_hw1");
    glutDisplayFunc(grid);
    glutMainLoop();
    return 0;
}

相关文章

[置顶] 可在右侧“网站分类”按分类浏览

可在右侧“网站分类”按分类浏览...