diff --git a/lab1/freeglut.dll b/lab1/freeglut.dll new file mode 100644 index 0000000..1feaac4 Binary files /dev/null and b/lab1/freeglut.dll differ diff --git a/lab2/lab2.cpp b/lab2/lab2.cpp new file mode 100644 index 0000000..aa48fd0 --- /dev/null +++ b/lab2/lab2.cpp @@ -0,0 +1,175 @@ +#include +#include + +// --- 定义区域编码 --- +#define INSIDE 0 // 0000 +#define LEFT 1 // 0001 +#define RIGHT 2 // 0010 +#define BOTTOM 4 // 0100 +#define TOP 8 // 1000 + +// --- 定义裁剪窗口结构 --- +struct ClipWindow { + float xmin, xmax, ymin, ymax; +}; + +// --- 全局变量设置 --- +ClipWindow rect; +int x_0, y_0, x_1, y_1; // 线段端点 + +/** + * 计算点 (x, y) 的区域编码 + */ +int computeCode(float x, float y, ClipWindow rect) { + int code = INSIDE; + if (x < rect.xmin) code |= LEFT; + else if (x > rect.xmax) code |= RIGHT; + if (y < rect.ymin) code |= BOTTOM; + else if (y > rect.ymax) code |= TOP; + return code; +} + +/** + * Cohen-Sutherland 算法核心 + * 注意:这里传入坐标的引用,直接修改坐标值以得到裁剪后的结果 + */ +void cohenSutherlandClip(float& x_0, float& y_0, float& x_1, float& y_1, ClipWindow rect) { + int code1 = computeCode(x_0, y_0, rect); + int code2 = computeCode(x_1, y_1, rect); + bool accept = false; + + while (true) { + // 如果两端点都在窗口内 (0000 | 0000 == 0) + if (!(code1 | code2)) { + accept = true; + break; + } + // 如果两端点都在窗口的同一侧外部 (例如都在左边:0001 & 0001 != 0) 按位与运算 + else if (code1 & code2) { + break; // 直接舍弃 + } + // 3. 线段部分在窗口内,需要求交点 + else { + int code_out; + float x, y; + + // 选择窗口外的一个端点 + if (code1 != 0) + code_out = code1; + else + code_out = code2; + + // 计算交点 + if (code_out & TOP) { + x = x_0 + (x_1 - x_0) * (rect.ymax - y_0) / (y_1 - y_0); + y = rect.ymax; + } + else if (code_out & BOTTOM) { + x = x_0 + (x_1 - x_0) * (rect.ymin - y_0) / (y_1 - y_0); + y = rect.ymin; + } + else if (code_out & RIGHT) { + y = y_0 + (y_1 - y_0) * (rect.xmax - x_0) / (x_1 - x_0); + x = rect.xmax; + } + else if (code_out & LEFT) { + y = y_0 + (y_1 - y_0) * (rect.xmin - x_0) / (x_1 - x_0); + x = rect.xmin; + } + + // 用交点替换原来的外部端点 + if (code_out == code1) { + x_0 = x; y_0 = y; + code1 = computeCode(x_0, y_0, rect); + } + else { + x_1 = x; y_1 = y; + code2 = computeCode(x_1, y_1, rect); + } + } + } + + // 如果接受,则绘制裁剪后的线段(蓝色) + if (accept) { + glBegin(GL_LINES); + glColor3f(0.0f, 0.0f, 1.0f); // 蓝色 + glVertex2f(x_0, y_0); + glVertex2f(x_1, y_1); + glEnd(); + } +} + +// --- 显示回调函数 --- +void myDisplay() { + glClear(GL_COLOR_BUFFER_BIT); + + // 1. 绘制裁剪窗口 (红色线框) + glColor3f(1.0f, 0.0f, 0.0f); // 红色 + glBegin(GL_LINE_LOOP); + glVertex2f(rect.xmin, rect.ymin); + glVertex2f(rect.xmax, rect.ymin); + glVertex2f(rect.xmax, rect.ymax); + glVertex2f(rect.xmin, rect.ymax); + glEnd(); + + // 2. 绘制原始线段 (绿色) + // 注意:为了演示效果,我们在调用裁剪函数前,先保存原始坐标, + // 或者在这里直接用初始值绘制。这里我们使用初始值绘制。 + int orig_x_0 = 50, orig_y_0 = 350; + int orig_x_1 = 550, orig_y_1 = 50; + + glBegin(GL_LINES); + glColor3f(0.0f, 1.0f, 0.0f); // 绿色 + glVertex2f(orig_x_0, orig_y_0); + glVertex2f(orig_x_1, orig_y_1); + glEnd(); + + // 3. 执行裁剪并绘制结果 (蓝色) + // 使用 float 变量传入,因为算法内部会修改它们 + float cx_0 = orig_x_0, cy_0 = orig_y_0; + float cx_1 = orig_x_1, cy_1 = orig_y_1; + + // 加粗蓝色线条以便区分 + glLineWidth(3.0); + cohenSutherlandClip(cx_0, cy_0, cx_1, cy_1, rect); + glLineWidth(1.0); // 恢复线宽 + + glFlush(); +} + +// --- 初始化设置 --- +void Init() { + glShadeModel(GL_FLAT); + + rect.xmin = 100; + rect.xmax = 400; + rect.ymin = 100; + rect.ymax = 300; +} + +// --- 窗口大小调整 --- +void myReshape(int w, int h) { + glViewport(0, 0, (GLsizei)w, (GLsizei)h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + // 设置二维投影范围,与坐标数值对应 + gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h); + glMatrixMode(GL_MODELVIEW); +} + +// --- 主函数 --- +int main(int argc, char* argv[]) { + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); + glutInitWindowPosition(100, 100); + glutInitWindowSize(600, 400); + glutCreateWindow("实验2_03毕爽爽 Cohen-Sutherland 算法"); + + Init(); + + glutDisplayFunc(myDisplay); + glutReshapeFunc(myReshape); + + glutMainLoop(); + return 0; +} \ No newline at end of file