珍蜗蜗

不断向前

导航

习题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来解答这道题目。

 

commit: 6ee4159541b305fadd2bf88b1dbd950558e12e8e