[计算机图形学 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 }

  因为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 }

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

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

commit: 6ee4159541b305fadd2bf88b1dbd950558e12e8e

时间: 2024-10-23 14:15:07

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

[计算机图形学 with OpenGL] Chapter8 习题8.12 NLN二维线段裁剪算法实现

Nicholl-Lee-Nicholl二维线段裁剪算法相对于Cohen-Sutherland和Liang-Barsky算法来说,在求交点之前进行了线段端点相对于几个区域的判断,可以确切的知道要求交点的边的信息. 此方法只在二维空间裁剪时使用,C-S和L-B裁剪方法则可应用到三维空间. 算法步骤: 1 先使用C-S裁剪算法的区域码判断方法,去除一部分在裁剪区域外面的线段.显示在完全在裁剪区域内的线段.其他不能判断的情况,采用NLN算法进行裁剪. 2 p1和p2若有一点在区域内,必要时交换端点以确保

计算机图形学和OpenGL(二)坐标系和绘制点线函数

这节开始前我们先了解一下图元的概念.图形软件包中用来描述各种图形元素的函数称为图形输出原语,也称图元(primitive).而描述对象几何要素的输出图元一般称为几何图元.点和线是最简单的几何图元,本节就会简单介绍点和线段的绘制方法. 一.坐标系统. 坐标系统一般分为屏幕坐标和OpenGL中的绘图坐标. 在上一节中我们简单的写了个示例程序,程序中介绍了gluOrtho2D命令.我们可以利用该命令设定一个二维笛卡尔坐标系.该函数的四个变量制定的是显示图形x和y坐标范围.所以我们可以使用下面代码制定一

【计算机图形学】OpenGL+VS2015相关类库配置

1 WiKi OpenGL一直是事实上的计算机图形学标准,截止2016年06月,OpenGL版本已经更新到4.5.不过DirectX发展迅速,大有OpenGL落后的态势,知乎上的该话题的讨论:https://www.zhihu.com/question/23241456.所以OpenGL为了追赶DirectX,推出 了glNext(Vulkan API),相关讨论https://www.zhihu.com/question/28039310. 2 相关资料 图形学的经典书籍是<Computer

[图形学] 计算机图形学 with OpenGL第一篇

<计算机图形学>(第四版)正在学习中,学习目的是为了在Unity中使用shader实现不同的渲染效果. 希望在这里能把学习过程中学到的知识和遇到的问题记录下来. 工作环境是:Xcode8.3.2. 代码目录是:https://github.com/p0e0o0p0l0e0/Computer_Graphics.git 目标学习内容有以下几章,已经学到第8章. 第3章:计算机图形学软件 第4章:输出图元 第5章:图元的属性 第6章:实现图元及属性的算法 第7章:二维几何变换 第8章:二维观察 第9

【计算机图形学】--OpenGl环境配置

一.配置环境 选择编程环境为Visual studio 2010 Visual studio 2010 中已经提供了对opengl库的支持,所以主要需要配置的是GLUT. GLUT是一个与窗口系统无关的工具包. 当写opengl程序时,可以通过GLUT实现简单的窗口的创建等操作,免去了学习特定OS下GUI库的过程. 二.配置过程 第一步:下载GLUT工具包 po写的刚开始学习,是在学校老师的课程主页下载的. 现上传至百度网盘:有需自取 [http://pan.baidu.com/s/1o8mDh

【计算机图形学】openGL常用函数

OpenGL常用函数   glAccum 操作累加缓冲区   glAddSwapHintRectWIN 定义一组被 SwapBuffers拷贝的三角形   glAlphaFunc允许设置alpha检测功能   glAreTexturesResident 决定特定的纹理对象是否常驻在纹理内存中   glArrayElement 定义一个被用于顶点渲染的数组成分   glBegin,glEnd 定义一个或一组原始的顶点   glBindTexture 允许建立一个绑定到目标纹理的有名称的纹理  gl

[计算机图形学 with OpenGL] Chapter10 OpenGL三维观察程序示例

10.10节书中给出了一个程序示例,有一个填充正方形,从侧面的角度观察并画到屏幕上. 图0 这里进一步画出一个立方体,将相机放入立方体中心,旋转相机,达到在立方体中旋转看到不同画面的效果. 步骤: 1 使用的是4.9节中的OpenGL顶点数组方法.创建一个立方体100*100*100,坐标范围(0, 0, 0)到(100, 100, 100). 2 立方体各面使用不同的颜色,调整顶点顺序以确保相机看到的都是填充面而不是线框图. 3 将投影观察点(即观察系原点)设置在矩形中心P0 = (50, 5

计算机图形学(二)输出图元_6_OpenGL曲线函数_2_中点画圆算法

中点画圆算法 如同光栅画线算法,我们在每个步中以单位间隔取样并确定离指定圆最近的像素位置.对于给定半径r和屏幕中心(xc,yc),可以先使用算法计算圆心在坐标原点(0, 0)的圆的像素位置,然后通过将xc加到x且yc加到y.从而把计算出的每个位置(x,y)移动到其适当的屏幕位置.在第一象限中,圆弧段从x = 0到x = y,曲线的斜率从0变化到-1.0.因此,可以在该八分圆上的正x方向取单位步长,并使用决策参数来确定每一步两个可能的y位置中,哪一个更接近于圆的位置.然后,其他七个八分圆中的位置可

Cohen Sutherland裁剪算法并使用OpenGL实践

还是其几天写的,这是最简单的一个直线裁剪算法了吧,它针对的是一个矩形和一条线段.并且还是边与坐标轴平行的矩形. 在实际应用上应该会经常用于屏幕对各种线段的裁剪吧.算法很简单效率也很高. 首先是算法的两种特例:平凡接受和平凡拒绝. (图片来自<计算机图形学(OpenGL)>第三版) 当线段的两个端点都在矩形内部,则平凡接受,不需要裁剪.如图中的AB.而当线段的两个端点都在某条边的外边时,平凡拒绝,也不需要裁剪.如图中的CD. 检测这两种情况的方法可以先形成两个端点的码字,如下: 那么可以得到如下