830 likes | 1.04k Views
课程内容进展. 综述. ‘ 图形学’和‘图形系统’. 建模 观察 显示. 曲线曲面 实体造型. 坐标系统. 基本图元. 观察流水线 裁剪. 几何变换. 可见面判别 光照 面绘制. 其它. UI 动画 ……. 第二讲 图元和图元属性. Graphics Primitives Attributes of Graphics Primitives. 图元的分类. 多边形填充区 像素阵列(位图) 字符. 点 直线 折线 曲线 圆(弧) 椭圆 其 它曲线.
E N D
课程内容进展 综述 ‘图形学’和‘图形系统’ • 建模 • 观察 • 显示 曲线曲面 实体造型 坐标系统 基本图元 观察流水线 裁剪 几何变换 可见面判别 光照 面绘制 • 其它 UI 动画 ……
第二讲 图元和图元属性 Graphics Primitives Attributes of Graphics Primitives
图元的分类 • 多边形填充区 • 像素阵列(位图) • 字符 • 点 • 直线 • 折线 • 曲线 • 圆(弧) • 椭圆 • 其它曲线 模型 图元 输出
图元的输出 • 扫描转换:(观察坐标系设备坐标系) • 几何坐标->屏幕坐标 (实数 -> 整数) • 图形精度,转换算法的时间(空间)复杂度 • 屏幕坐标:整数,和帧缓存中的像素位置对应, • 屏幕上边 y=0 • 屏幕下边 y=ymax • 屏幕左边 x=0 • 屏幕右边 x=xmax 0,0 xmax,ymax
第二讲主要内容 各类图元的输出方法 • 扫描转换算法 • 直线 • 圆 • 多边形填充 • OpenGL相关函数简介 各类图元的属性 • 属性生成算法 • OpenGL相关函数简介 • 反走样
第二讲小结 • 图形系统中基本图元在屏幕上的生成方法 • 点:与帧缓存位置对应 • 直线:bresenham算法 • 圆:中点算法 • 填充区:扫描线方法,活动边表的使用 • 各种图元的属性 • 线型属性的生成方法:掩模 • 线宽属性的生成方法:水平,垂直,填充 • 填充属性的生成方法:扫描线,图案 • 反走样方法
计算练习 • 假设系统有一个8英寸×10英寸、每英寸能显示100个像素的监视器。如果存储器的字长为一字节,起始帧缓存地址为0,并且每个像素对应存储器的1个字节,那屏幕坐标(x,y)在帧缓存中的地址是什么? • 一个四边形的四个顶点坐标依次为 (1,1) (3,1) (5,4) (3,6) 欲使用扫描线多边形填充算法对该四边形填充,请给出边表和活动边表内容。
编程练习 • 允许用户任意输入a,b以及x坐标范围,输出y=ax+b的扫描转换结果(采用Bresenham算法) • 输入若干组顶点坐标和另一个点坐标P (采用右手笛卡儿系) • 对每组顶点(如果数量>3) ,判断是否共面 • 如果分别共面,继续判断几个面片是否能构成一个三维对象表面 • 如果可以构成一个三维对象,再判断P是否在对象内部 • 用掩模的方法自定义笔刷并实现画线函数(注意避免重复点的绘制)
点的输出 • (x,y)-帧缓存地址-像素颜色等 • 分辨率 H * V • 每个像素1位 • (0,0) Addr(0,0) • (x,y) Addr(0,0) + y * H + x • Addr(x+1,y) Addr(x,y) + 1 • Addr(x+1,y+1) Addr(x,y) + H + 1
线的输出 • 核心问题:取样&像素计算
斜率截距法 y = m * x + b DDA (Digital Differential Analyzer) 斜率 |m| <= 1时 Xk+1 = Xk + 1 (从线条左端开始) Yk+1 = Yk + m 斜率 |m| >= 1时 Yk+1 = Yk + 1 (从线条下端开始) Xk+1 = X + 1/m 画线算法:斜率截距法、DDA法 y b x 实数乘法、加法,取整操作 实数加法,取整操作
画线算法:Bresenham • 思想: • x 每次增加 1 (|m|<1) • 判断(x+1, y+1)和(x+1, y)哪个更接近线条 • 用整数加减法计算y的增量 • 假设 : 0 < m < 1 • 始点在线条的最左端 起始、终止点均变化为整数
yk+1 d2 y d1 yk xk xk+1 y = m (xk+1) + b d1 = y - yk = m ( xk+ 1) + b - yk d2 = ( yk + 1 ) - y= yk + 1- m ( xk + 1 ) - b d1-d2 = 2m ( xk + 1 ) - 2yk + 2b- 1 m = △y / △x △x>0,定义决策参数p pk = △x ( d1 - d2 ) = 2△y . xk - 2△x . yk+ c c= 2△y + △x(2b-1) pk+1 = 2△y . xk+1 - 2△x. yk+1+ c pk+1 - pk = 2△y (xk+1 - xk ) - 2△x (yk+1 - yk )= 2△y - 2△x (yk+1 - yk ) pk+1 = pk + 2△y - 2△x (yk+1 - yk ) if pk <0 , d1 - d2 <0 , yk+1= yk,yk+1 - yk =0, pk+1 = pk + 2△y ifpk >=0, d1 - d2 >=0, yk+1= yk + 1,yk+1 - yk = 1, pk+1 = pk + 2△y-2△x (x0 y0 )为第一个屏幕像素,p0 =2△y . x0 - 2△x . y0+ c = 2△y - △x 整数加法,正负性判断
Bresenham画线 例图 (x0 y0) p0 = 2△y - △x p0>=0 p0<0 (x0+1,y0) p1 = p0+2△y (x0+1, y0+1 ) p1 = p0 + 2△y -2 △x ……
并行画线算法 • 每处理器一段线,分别使用 Bresenham 算法 • 每处理器一行(列)扫描线,计算与线交点 • 每处理器一块屏幕像素,甚至一个屏幕像素,计算像素与线条的垂直距离是否小于线宽
圆的输出 • 核心问题:取样&像素计算 • 圆的八对称性
中点圆生成算法 • f(x,y)=x2+y2-r2 • 每次 x 加 1 • 判断 (x+1, y – 0.5) 在圆内还是圆外 • 其它7个分区内的像素通过对称性直接得到 yk yk-1 Middle xk+1 xk+2 xk
yk 中点圆算法推导 yk-1 Middle xk+1 xk+2 xk • f(x,y)=x2+y2-r2 pk =f(xk+1,yk-0.5)= (xk+1)2+(yk-0.5)2- r2 pk+1=f(xk+1+1,yk+1-0.5)= (xk+1+1)2+(yk+1-0.5)2 -r2 =pk+2(xk+1)+(yk+12-yk2)- (yk+1-yk)+1 if (pk<0) yk+1=ykpk+1= pk+2xk+1+1 (中点在圆内,取上) if (pk>=0) yk+1= yk-1 pk+1=pk+2xk+1+1-2yk+1 (在圆外,取下) 2xk+1= 2xk+2 2yk+1= 2yk-2 初始位置:(0,r) p0=f(1,r-0.5)=1+(r-0.5)2-r2 = 1.25 - r = 1-r (r是整数)
圆的Bresenham算法 A B Pi-1 Si C D(Si)=[(Xi-1+1)2+(Yi-1)2]-R2 D(Ti)=[(Xi-1+1)2+(Yi-1-1)2]-R2 对C, D(Si)>0, D(Ti)<0 |D(Si)|-|D(Ti)|=D(Si)+D(Ti) 令 di= D(Si)+D(Ti)=2(Xi-1+1)2+(Yi-1)2+(Yi-1-1)2-2R2 若di>=0 Pi=Ti 若di<0 Pi=Si 对A,B应选SiD(Si), D(Ti)<=0 di<0 对D,E,F,G应选TiD(Si), D(Ti)>=0 di>=0 判别式di普遍成立 D E F G Ti
选代公式 Pi-1 Si P0(0,R) S1(1,R) T1(1,R-1) d1= D(S1)+D(T1)=1+(2-2R)=3-2R Xi =Xi-1+1 if di<0 Yi = Yi-1 if di>=0 Yi = Yi-1-1 di+1=D(Si+1)+D(Ti+1)=2(Xi+1)2+(Yi)2+(Yi-1)2-2R2 =2(Xi-1+1+1)2+(Yi-1)2+(Yi-1-1)2-2R2 = di+4xi-1+6 if di<0 2(Xi-1+1+1)2+(Yi-1+1)2+(Yi-1+1-1)2-2R2= di+4(xi-1+yi-1)+10 if di>=0 Ti
椭圆、其它曲线 • 椭圆:四对称性。在每个分区,需要通过斜率判断下一步应该使用x还是y的增量 • 双曲线、抛物线、圆锥曲线等均可以用中点算法来实现 • 多项式和样条曲线
多边形:凹凸性、内点判断 • 凸多边形:每个内角<180 • 凹多边形:至少一个内角>180 • 判断方法:矢量叉乘符号判断法 • 内点判断方法: • 奇偶规则(求交点) • 非零环绕数规则 • u和边向量叉积 • u’和边向量点积 u’ u u u u
附:奇偶规则中交点计数特例 当射线与多边形 • 交于某顶点、且该顶点的两个邻边在射线的两侧时,计数1次; • 交于某顶点、且该顶点的两个邻边在射线的同侧时,计数0次; • 某边重合、且该边的两个邻边在射线的两侧时,计数1次; • 某边重合、且该边的两个邻边在射线的同侧时,计数0次; 0 1 1 1 1 0 1 0 1
多边形分割 • 凸多边形分割为三角形 • 相邻三点连成三角形 • 凹多边形分割: • 分割为凸多边形: • 矢量法,旋转法 • 分割为三角形: • 相邻三点不可构成内角>180 矢量法
利用多边形的对象表示 • 几何数据表 • 点、边和面 • 属性数据表 • 透明性 • 反射性 • 纹理 • 颜色 • ……
多边形平面,平面方程 • 平面方程Ax+By+Cz+D = 0的应用 • 计算逼近平面 • 平均值法 • 投影方法 • 前向(后向)面的判断:右手规则 • Ax+By+Cz+D > 0 :点在平面前方 • Ax+By+Cz+D < 0 :点在平面后方 • 平面法向量(normal vector)为(A,B,C):从平面后方指向前方,与平面垂直 • 反之,矢量叉乘计算法向量,从而可得出平面参数
多边形扫描填充算法 • 原理 • 关键问题 • 求交 • 分段 • 计算
y+1 y x + 1/m x • 相关性计算方法(提高算法效率):相邻扫描线与同一边的交点坐标可利用斜率快速计算 • 多边形的各条边何时需要开始求交?
边表 Edge Table(针对直线边界多边形) • 非水平线 • 按最小y值排序 • 单调递增(减)连接处将y减小一个单位 • 存储桶(桶排序)
(1,10) 边表 (7,7) 11 10 9 (3,3) 8 7 6 (5,1) (1,1) 5 4 2 7 3 1 10 3 - 3 7 2 1 7 5 10 1 0 1 3 0 • 活动边表 Active Edge Table • 当前扫描行相关各边信息按从左到右排列成表(按x值排序) • 随着扫描的进行,活动边表内容不断变化
活动边表-1 (1,10) (7,7) 11 10 (3,3) 9 8 7 (5,1) (1,1) 6 5 4 3 2 1 7 5 10 1 0 1 3 0
活动边表-2 (1,10) (7,7) 11 10 9 (3,3) 8 7 6 (5,1) (1,1) 5 4 3 1 1 7 5 10 1 0 2 3 3 1 0
(1,10) 活动边表-3 (7,7) 11 10 9 (3,3) 8 7 (5,1) 6 (1,1) 5 4 2 10 3 - 10 1 0 3 7 2 1 0 1 2 7 3 1 7 5 3 3
(1,10) 活动边表-4 (7,7) 11 10 (3,3) 9 8 7 (5,1) (1,1) 6 5 4 2 5 10 2 - 10 1 0 7 7 3 2 1 1 7 4 1 7 6 3 0 ·········
OpenGL画点、画线 glBegin(GL_POINTS) glVertex*(x,y); glEnd; 【glVertex 2/3i/f(v) 】 Glint p1[ ] = {x1,y1}, p2[ ] = {x2,y2}… glBegin(GL_LINES) GL_LINE_STRIPGL_LINE_LOOP glVertex2iv(p1); glVertex2iv(p2); glVertex2iv(p3); glVertex2iv(p4); glVertex2iv(p5); glEnd;
OpenGL画曲线 • 核心库:生成Bezier样条的函数(根据离散控制点计算) • GLU:球面、柱面等三维曲面函数,生成B样条的函数(有理B样条可用来显示圆、椭圆等二维曲线) • GLUT:三维曲面(球面、锥面)函数 • 折线近似法 • 自定义的二维曲线生成函数
OpenGL多边形填充 glRecti(x1,y1,x2,y2); (glRectv(p1,p2);) glBegin(GL_POLYGON) GL_TRIANGLESGL_TRIANGLE_STRIPGL_TRIANGLE_FAN GL_QUADSGL_QUAD_STRIP glVertex2iv(p1); … glVertex2iv(pN); glEnd;
多边形填充图示 glRecti(v) glBegin(GL_TRIANGLES) 顺序:1,2,6,3,4,5 glBegin(GL_POLYGON) 顺序:1,2,3,4,5,6 glBegin(GL_TRIANGLE_STRIP) 顺序:1,2,6,3,5,4 glBegin(GL_TRIANGLE_FAN) 顺序:1,2,3,4,5,6
多边形填充图示 glBegin(GL_QUADS) 顺序:1,2,3,4,5,6,7,8 glBegin(GL_QUAD_STRIP) 顺序:1,2,4,3,5,6,8,7
OpenGL像素阵列 P glBitmap(width, height, x0, y0, xoffset, yoffset, bitShape); glDrawPixels(width, height, dataFormat, dataType, pixMap); R 1 1
OpenGL字符函数 用轮廓字体绘制字符 glutStrokeCharacter(font, character); 用位图字体绘制字符 glutBitmapCharacter (font, character);
OpenGL用于二维显示 //视口位置和尺寸(相对于程序窗口) glViewport (x, y, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); //二维投影面,决定了二维显示坐标的范围 gluOrtho2D(xmin,xmax,ymin,ymax); 显示器屏幕 指定观察设备的关联方式 视口范围 指定观察方式 Opengl程序窗口 xmax,ymax 在世界坐标系下指定观察范围 二维投影面范围 xmin,ymin
有关“属性” • 属性参数:任何影响图元显示方法的参数 • 颜色、大小。。。 • 三维视图的深度信息,可见性。。。 • 属性控制方法 • 和几何参数一起设置 • 状态设置法: • 设置状态变量或状态参数 • 不影响其前只影响其后的图元显示
1. 点属性 • 大小size • 整数 • Size>1的点就是一个方块 • glPointSize (size) • 颜色