首页 > 代码库 > [计算机图形学 with OpenGL] Chapter8 习题8.6 线段旋转后使用Cohen-Sutherland算法裁剪

[计算机图形学 with OpenGL] Chapter8 习题8.6 线段旋转后使用Cohen-Sutherland算法裁剪

习题8.6 生成一条比观察窗口对角线还长的线段动画,线段重点位于观察窗口中心,每一帧的线段在上一帧基础上顺时针旋转一点,旋转后用Cohen-Sutherland线段裁剪算法进行裁剪。

步骤:

  • 1 视口范围:(-100, -100)到(100, 100);
  • 2 裁剪窗口区域:winMin(-50, -50) 到 winMax(50, 50),原始端点:p0(-100, 0)到 p1(100, 0)
  • 3 使用Bresenham算法画原始线段,使用Cohen-Sutherland算法画裁剪线段;
  • 4 theta += delta,其中 theta为累计旋转角度,delta为每次变化的角度;
  • 5 计算旋转后的新的原始线段端点:p0‘和p1‘。x‘ = x * cos(theta) - y * sin(theta), y‘ = x * sin(theta) +y * cos(theta);
  • 6 每帧重复步骤3-5.
技术分享
 1 #include <GLUT/GLUT.h> 2 #include <math.h> 3 #include <iostream> 4 #include "linebres.h" 5 #include "linecohsuth.h" 6  7 const GLdouble PI = 3.1416; 8 GLdouble theta = 0.0; 9 const GLdouble delta = - PI / 100;10 11 void init (void)12 {13     glClearColor(0.0, 0.0, 0.0, 1.0);14     15     glMatrixMode(GL_PROJECTION);16     gluOrtho2D(-100, 100, -100, 100);17     18     glMatrixMode(GL_MODELVIEW);19 }20 21 void clippingWindow (void)22 {23     glColor3f(1.0, 1.0, 1.0);24     25     glBegin(GL_LINE_LOOP);26     glVertex2i(-50, -50);27     glVertex2i(-50, 50);28     glVertex2i(50, 50);29     glVertex2i(50, -50);30     glEnd();31 }32 33 void displayFcn (void)34 {35     glClear(GL_COLOR_BUFFER_BIT);36     37     clippingWindow();38     39     glColor3f(1.0, 1.0, 1.0);40     41     wcPt2D winMin, winMax;42     winMin.setCoords(-50, -50);43     winMax.setCoords(50, 50);44     45     wcPt2D p0, p1;46     p0.setCoords(-100, 0);47     p1.setCoords(100, 0);48     49     wcPt2D p00, p01;50     p00.setCoords(p0.getx() * cos(theta) - p0.gety() * sin(theta), p0.getx() * sin(theta) + p0.gety() * cos(theta));51     p01.setCoords(p1.getx() * cos(theta) - p1.gety() * sin(theta), p1.getx() * sin(theta) + p1.gety() * cos(theta));52     53 //    std::cout << "p00 : " << p00.getx() << "," << p00.gety() << std::endl;54 //    std::cout << "p01 : " << p01.getx() << "," << p01.gety() << std::endl;55     56     glColor3f(1.0, 1.0, 0.0);57     lineBres(round(p00.getx()), round(p00.gety()), round(p01.getx()), round(p01.gety()));58     glColor3f(0.0, 1.0, 1.0);59     lineClipCohSuth(winMin, winMax, p00, p01);60     61     glutSwapBuffers();62 }63 64 void idleFcn (void)65 {66     theta += delta;67     displayFcn();68 }69 70 int main(int argc, char * argv[]) {71 72     glutInit(&argc, argv);73     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);74     glutInitWindowPosition(-50, 50);75     glutInitWindowSize(600, 600);76     glutCreateWindow("Exercise 8.6");77     78     init();79     glutDisplayFunc(displayFcn);80     glutIdleFunc(idleFcn);81     82     glutMainLoop();83     84     return 0;85 }
View Code

  因为theta一直在变化,每次重新计算cos(theta)和sin(theta)会影响效率,因此p0和p1每次更新为旋转后的坐标,修改代码如下:

技术分享
 1 #include <GLUT/GLUT.h> 2 #include <math.h> 3 #include <iostream> 4 #include "linebres.h" 5 #include "linecohsuth.h" 6  7 const GLdouble PI = 3.1416; 8 const GLdouble delta = - PI / 100; 9 GLint initialized = 0;10 GLdouble cosDelta, sinDelta;11 wcPt2D p0, p1, winMin, winMax;12 13 void init (void)14 {15     glClearColor(0.0, 0.0, 0.0, 1.0);16     17     glMatrixMode(GL_PROJECTION);18     gluOrtho2D(-100, 100, -100, 100);19     20     glMatrixMode(GL_MODELVIEW);21 }22 23 void clippingWindow (void)24 {25     glColor3f(1.0, 1.0, 1.0);26     27     glBegin(GL_LINE_LOOP);28     glVertex2i(-50, -50);29     glVertex2i(-50, 50);30     glVertex2i(50, 50);31     glVertex2i(50, -50);32     glEnd();33 }34 35 void displayFcn (void)36 {37     glClear(GL_COLOR_BUFFER_BIT);38     39     clippingWindow();40     41     glColor3f(1.0, 1.0, 1.0);42     43     if(!initialized)44     {45         initialized = 1;46         cosDelta = cos(delta);47         sinDelta = sin(delta);48         winMin.setCoords(-50, -50);49         winMax.setCoords(50, 50);50         p0.setCoords(-100, 0);51         p1.setCoords(100, 0);52     }53     54     p0.setCoords(p0.getx() * cosDelta - p0.gety() * sinDelta, p0.getx() * sinDelta + p0.gety() * cosDelta);55     p1.setCoords(p1.getx() * cosDelta - p1.gety() * sinDelta, p1.getx() * sinDelta + p1.gety() * cosDelta);56     57     glColor3f(1.0, 1.0, 0.0);58     lineBres(round(p0.getx()), round(p0.gety()), round(p1.getx()), round(p1.gety()));59     glColor3f(0.0, 1.0, 1.0);60     lineClipCohSuth(winMin, winMax, p0, p1);61     62     glutSwapBuffers();63 }64 65 int main(int argc, char * argv[]) {66 67     glutInit(&argc, argv);68     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);69     glutInitWindowPosition(-50, 50);70     glutInitWindowSize(600, 600);71     glutCreateWindow("Exercise 8.6");72     73     init();74     glutDisplayFunc(displayFcn);75     glutIdleFunc(displayFcn);76     77     glutMainLoop();78     79     return 0;80 }
View Code

 

  本来想使用glRotatef(delta, 0.0, 0.0, 1.0)这个转换矩阵进行旋转,但使用C-S裁剪算法时传入的端点坐标依然不是旋转后的,先裁剪后旋转导致裁剪区域不对。不知道是否可以用glRotatef来解答这道题目。

 

完整代码地址:https://github.com/p0e0o0p0l0e0/Computer_Graphics/
commit: 6ee4159541b305fadd2bf88b1dbd950558e12e8e 

 

[计算机图形学 with OpenGL] Chapter8 习题8.6 线段旋转后使用Cohen-Sutherland算法裁剪