计算机图形学实验——直线和圆的绘制
程序员文章站
2022-07-14 10:09:39
...
实验目的
1.本次实验着重学习以下常用函数,在实验报告中的实验原理部分对下列函数进行参数介绍和用法介绍。glBegin(GL_POINTS)
glVertex()
绘制一个点glEnd();
glLoadIdentity();
设置投影参数:glMatrixMode(GL_PROJECTION);
视景体裁剪(创建一个正交平行的视景体,即正投影):glOrtho(left, right, bottom, top, near, far);
2.数字微分法(DDA)绘制一条直线,直线起点坐标为(-100,-100)
,终点为(50,20)
。中点Brensenham算法绘制一条直线,直线起点坐标为(-100,-100)
,终点为(50,-10)
3.用中点Bresenham算法绘制一个圆心点在(0,0)
,半径为20的圆
4.绘制棋盘
实验结果
最终结果通过改变main函数中
glutDisplayFunc();
决定展示哪一个效果
#include<gl/glut.h>
#include<cmath>
void dda(float x1, float y1, float x2, float y2);
void MidpointLine(float xs, float ys, float xe, float ye);
void ManyGlVertex2f(float absX, float absY, float x, float y);
void Bresenham(float xs, float ys, float xe, float ye);
void pnarc(float radius, float m, float n);
void bresenham_arc(float R, float m, float n);
void myinit(void);
//直线DDA法
void dda(float x1, float y1, float x2, float y2) {
float k, i;
float x, y, dx, dy;
k = fabsf(x2 - x1);
if (fabsf(y2 - y1) > k)
k = fabsf(y2 - y1);
dx = float(x2 - x1) / k;
dy = float(y2 - y1) / k;
x = float(x1);
y = float(y1);
for (i = 0.0; i < k; i++) {
glVertex2f(x, y);
x = x + dx;
y = y + dy;
}
}
void Display1(void) {
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(2.0);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POINTS);
dda(-100, -100, 50, 20);
glEnd();
glFlush();
}
//直线正负法
void MidpointLine(float xs, float ys, float xe, float ye) {
float a, b, dt1, dt2, d, x, y;
float absY = ye - ys;
float absX = xe - xs;
//采用对称的方法来绘画其他象限的图案
if ((fabsf(absY) > fabsf(absX)) && absX > 0 && absY > 0) {//斜率大于1
float m = ys;
ys = xs;
xs = m;
float n = ye;
ye = xe;
xe = n;
}
else if (absY < 0 && absX>0 && (fabsf(absY) <= fabs(absX))) {
ys = -ys;
ye = -ye;
}
else if (absY < 0 && absX>0 && (fabsf(absY) > fabs(absX))) {
float m = ys;
ys = xs;
xs = -m;
float n = ye;
ye = xe;
xe = -n;
}
else {//斜率0到1
//do nothing
}
a = ys - ye;
b = xe - xs;
d = 2 * a + b;
dt1 = 2 * a;
dt2 = 2 * (a + b);
x = xs; y = ys;
ManyGlVertex2f(absX, absY, x, y);
while (x < xe) {
if (d < 0) {
x++;
y++;
d = d + dt2;
}
else {
x++; d = d + dt1;
}
ManyGlVertex2f(absX, absY, x, y); //调用ManyGlVertex2f()函数
}
//float maxY = getMax(ys, ye);
//float minY = getMin(ys, ye);
////画竖直的线
//if (xs == xe) {
// for (float i = minY; i <= maxY; i++) {
// glVertex2f(xs, i);
// }
//}
}
void ManyGlVertex2f(float absX, float absY, float x, float y) {
if ((fabsf(absY) > fabsf(absX)) && absX > 0 && absY > 0) {//斜率大于1
glVertex2f(y, x);
}
else if (absY < 0 && absX>0 && (fabsf(absY) <= fabs(absX))) {//斜率-1到0
glVertex2f(x, -y);
}
else if (absY < 0 && absX>0 && (fabsf(absY) > fabs(absX))) {//斜率小于-1
//printf("到这了\n");
glVertex2f(y, -x);
}
else {//斜率0到1
glVertex2f(x, y);
}
}
void Display2(void) {
glClear(GL_COLOR_BUFFER_BIT);//注意这几个glClear等函数放的位置
glPointSize(2.0);
glColor3f(1.0, 0.0, 0.0);/*用红色绘制对象*/
glBegin(GL_POINTS);
MidpointLine(-250, 250, 350, 200);
MidpointLine(50, -150, 350, 250);
MidpointLine(-450, 50, 0, 400);
MidpointLine(-570, 0, 570, 0);//x轴
MidpointLine(0, -570, 0, 570);//y轴
glEnd();
glFlush();
}
//直线Bresenham法
void Bresenham(float xs, float ys, float xe, float ye) {
float absY = ye - ys;
float absX = xe - xs;
//采用对称的方法来绘画其他象限的图案
if ((fabsf(absY) > fabsf(absX)) && absX > 0 && absY > 0) {//斜率大于1
float m = ys;
ys = xs;
xs = m;
float n = ye;
ye = xe;
xe = n;
}
else if (absY < 0 && absX>0 && (fabsf(absY) <= fabs(absX))) {//斜率-1到0
ys = -ys;
ye = -ye;
}
else if (absY < 0 && absX>0 && (fabsf(absY) > fabs(absX))) {//斜率小于-1
float m = ys;
ys = xs;
xs = -m;
float n = ye;
ye = xe;
xe = -n;
/*printf("xs=%f\n", xs);
printf("ys=%f\n", ys);
printf("xe=%f\n", xe);
printf("ye=%f\n", ye);*/
}
else {//斜率0到1
//do nothing
}
float dx = xe - xs;
float dy = ye - ys;
float m = (double)dy / (double)dx;
float e = m - 0.5;
float x, y;
x = xs;
y = ys;
for (int i = 0; i < dx; i++) {
ManyGlVertex2f(absX, absY, x, y); //调用ManyGlVertex2f()函数
if (e >= 0) {
y = y + 1; e = e - 1;
}
x = x + 1; e = e + m;
}
}
void Display3(void) {
glClear(GL_COLOR_BUFFER_BIT);//注意这几个glClear等函数放的位置
glPointSize(2.0);
glColor3f(1.0, 0.0, 0.0);/*用红色绘制对象*/
glBegin(GL_POINTS);
Bresenham(-100, -100, 50, -10);
//Bresenham(50, 150, 350, 250);
//Bresenham(-450, 50, 0, -400);
//Bresenham(-570, 0, 570, 0);//x轴
//Bresenham(0, -570, 0, 570);//y轴
dda(-100, -100, 50, 20);
glEnd();
glFlush();
}
//正负法
void pnarc(float radius, float m, float n) {
float x, y, f;
x = 0; y = 0 + radius; f = 0;
while (y > 0) {
glVertex2f(x + m, y + n);
glVertex2f(-x + m, y + n);
glVertex2f(-x + m, -y + n);
glVertex2f(x + m, -y + n);
if (f > 0) {
f = f - 2 * y + 1; y = y - 1;
}
else {
f = f + 2 * x + 1; x = x + 1;
}
}
if (y == 0) {
glVertex2f(x + m, y + n);
glVertex2f(-x + m, y + n);
glVertex2f(-x + m, -y + n);
glVertex2f(x + m, -y + n);
}
}
void Display4(void) {
glClear(GL_COLOR_BUFFER_BIT);//注意这几个glClear等函数放的位置
glPointSize(2.0);
glColor3f(1.0, 0.0, 0.0);/*用红色绘制对象*/
glBegin(GL_POINTS);
pnarc(150, -250, 250);
pnarc(150, 250, 250);
pnarc(150, 250, -250);
pnarc(150, -250, -250);
Bresenham(-570, 0, 570, 0);//x轴
Bresenham(0, -570, 0, 570);//y轴
glEnd();
glColor3f(0, 1, 0);
glBegin(GL_POINTS);
pnarc(150, 0, 0);
glEnd();
glFlush();
}
//Bresenham法
void bresenham_arc(float R, float m, float n) {
float x, y, d;
x = 0; y = R; d = 3 - 2 * R;
while (x < y) {
glVertex2f(x + m, y + n);
glVertex2f(y + m, x + n);
glVertex2f(y + m, -x + n);
glVertex2f(x + m, -y + n);
glVertex2f(-x + m, -y + n);
glVertex2f(-y + m, -x + n);
glVertex2f(-y + m, x + n);
glVertex2f(-x + m, y + n);
if (d < 0)
d = d + 4 * x + 6;
else {
d = d + 4 * (x - y) + 10;
y = y - 1;
}
x = x + 1;
}
if (x == y) {
glVertex2f(x + m, y + n);
glVertex2f(y + m, x + n);
glVertex2f(y + m, -x + n);
glVertex2f(x + m, -y + n);
glVertex2f(-x + m, -y + n);
glVertex2f(-y + m, -x + n);
glVertex2f(-y + m, x + n);
glVertex2f(-x + m, y + n);
}
}
void Display5(void) {
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(2.0);
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_POINTS);
bresenham_arc(20, 0, 0);
glEnd();
glFlush();
}
//调用以上函数绘制中国象棋的棋盘和棋子
void Display6(void) {
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(2.0);
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_POINTS);
for (float i = -360; i <= 360; i += 80) {
dda(-360, i, 360, i);
}
for (float i = -360; i <= 360; i += 90) {
dda(i, 40, i, 360);
}
for (float i = -360; i <= 360; i += 90) {
dda(i, -40, i, -360);
}
dda(-360, -40, -360, 40);
dda(360, -40, 360, 40);
float b = 90, c = 200, d = 360;
dda(-b, c, b, d);
dda(-b, d, b, c);
dda(-b, -d, b, -c);
dda(-b, -c, b, -d);
glEnd();
//画象棋图上的圆
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POINTS);
float R = 28;
for (float i = -360; i <= 360; i += 90) {
pnarc(R, i, 360);
pnarc(R, i, -360);
}
for (float i = -360; i <= 360; i += 180) {
pnarc(R, i, 120);
pnarc(R, i, -120);
}
for (float i = -270; i <= 320; i += 540) {
pnarc(R, i, 200);
pnarc(R, i, -200);
}
glEnd();
//最外侧直线
glPointSize(3.0);
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_POINTS);
float a = 380;
dda(-a, a, a, a);
dda(a, a, a, -a);
dda(a, -a, -a, -a);
dda(-a, -a, -a, a);
glEnd();
glFlush();
}
//设置属性
void myinit(void) {
glClearColor(1.0, 1.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-500.0, 500.0, -500.0, 500.0);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char * argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(20, 40); //设置位置
glutInitWindowSize(280, 280); //设置高宽
glutCreateWindow("OpenGL");
myinit();
glutDisplayFunc(Display6);
glutMainLoop();
return 0;
}