OpenGL光栅化作业:【bresenham算法】GL_POINTS为基础画圆
As usual先读题。
2.3 Draw a Circle
Implement your circle rasterization algorithm in OpenGL. You can only use integer arithmetic in your code.
- Input: A point as the center of a circle and a radius, that make 3 integers
- Output: A circle in a window
- You can only use the
GL_POINTS
as primitives. Others primitives or build-in draw is not allowed to use.
嘛,所以其实也是跟前面画线段的算法一样,也是用GL_POINTS画出足够多且密集的离散点在视觉意义上产生一个圆形。有很多类似的地方,控制输入范围为[-500,500]区间的整数再规格化到[-1,1]的浮点数等等,这些分析,就不废话了直接看前面那篇讲画线段的前半截就好。
由于在画圆方面没有什么思路,所以参考了一下网上的画圆算法。注明参考出处:http://www.cnblogs.com/gamesky/archive/2012/09/03/2668932.html
并且
由于数学确实差(……)所以也没有做算法推导,直接用了以上这篇博文推导出的结论。也就是:
【先假设圆心的坐标为原点】。
先算出从(0, r)到(r/√2, r/√2)之间的1/8圆弧的点的坐标值,其他部分直接用轴对称和中心对称变换,最后画出完整的圆形。
也就是计算出那特定的1/8圆弧上的点的坐标(x,y),再绘制出相应的(x, -y), (-x, y), (-x, -y), (y, x), (-y, x), (y, -x), (-y, -x)。
而那1/8圆弧上因为x上的变化比y大,所以在x方向上取样,在y方向上量化。递推思想就是:
d0=1-r
if d<0 d=d+2*x+3
if d>=0 d=d+2*(x-y)+5, y=y-1
x=x+1
并且直接在glBegin()和glEnd()之间用一个while(y>x)的循环,绘制出(x,y)和它相应的对称点就好,也不需要用画线段时导入数组的办法了(毕竟哪里一不小心就下标越界还占内存orz)。当然这里在调用glVertex的时候传入的参数(1)首先要是浮点数,所以仍然要做一个规格化处理normalize()。(2)要考虑到圆心坐标其实未必是原点的情况,对得到的浮点数坐标还要做一个浮点圆心坐标(fcx, fcy)的平移。
也就是
while(y>x) {float fx=normalize(x);float fy=normalize(y);//(x,y) (-x,-y) (-x,y) (x,-y)glVertex2f(fcx+fx,fcy+fy);glVertex2f(fcx-fx,fcy-fy);glVertex2f(fcx-fx,fcy+fy);glVertex2f(fcx+fx,fcy-fy);//(y,x) (-y,-x) (-y,x) (y,-x)glVertex2f(fcx+fy,fcy+fx);glVertex2f(fcx-fy,fcy-fx);glVertex2f(fcx-fy,fcy+fx);glVertex2f(fcx+fy,fcy-fx);if(d<0) {d=d+2*x+3;} else {d=d+2*(x-y)+5;--y;}++x;}
其次就是画完y>x部分的1/8圆弧和与其对称的圆弧之外,我发现这样写其实没有考虑到x=y,x=-y的点的情况。虽然这样圆看起来也没什么影响,但由于强迫症,所以还是加上一段:
//need the 4 points on the diagonalfloat diagonal=float(r)/sqrt(2);glVertex2f(fcx+diagonal,fcy+diagonal);glVertex2f(fcx-diagonal,fcy+diagonal);glVertex2f(fcx+diagonal,fcy-diagonal);glVertex2f(fcx-diagonal,fcy+diagonal);
不过我想了一下,在前面的while循环判断条件改成y>=x可能就好了,虽然可能会出现重复绘制的情况(……),不过写都写了就这样吧呵呵呵呵呵呵呵
然后如果看了前面那篇参考博文的内容,其他反正都挺好懂的就不讲废话了直接上完全代码。
1 #include <iostream> 2 #include <math.h> 3 #include <GLFW/glfw3.h> 4 using namespace std; 5 //g++ -o demo circle.cpp -lglfw3 -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo 6 float normalize(int input) { 7 return float(input)/500; 8 } 9 10 //-400 100 200 11 int main() { 12 int r, cx,cy; 13 cout << "Please give the coordinate of the center of the circle? like 'x y'" << endl 14 << "Notice: x and y should be integers between 0 and 500" << endl; 15 cin >> cx >> cy; 16 cout << "Please give the radius r of the circle" << endl 17 << "Notice: r should be an integer between 0 and 500" << endl; 18 cin >> r; 19 float fcx=normalize(cx); 20 float fcy=normalize(cy); 21 22 int x=0,y=r; 23 int d=1-r; 24 25 26 bool init = true; 27 if(!glfwInit()) { 28 cout << "Initialization failed" << endl; 29 init = false; 30 return -1; 31 } 32 33 //create a window with its OpenGL context 34 GLFWwindow* window1 = glfwCreateWindow(640, 640, "Circle", NULL, NULL); 35 36 if (!window1) { 37 cout << "Window or OpenGL context creation failed" << endl; 38 glfwTerminate(); 39 return -1; 40 } 41 if(init&&window1) { 42 // Make the window's context current */ 43 glfwMakeContextCurrent(window1); 44 45 while (!glfwWindowShouldClose(window1)) { 46 // Keep running 47 /* Draw a triangle */ 48 glBegin(GL_POINTS); 49 50 glColor3f(1, 0.52, 0.0); // Orange 51 //glVertex2f 52 53 while(y>x) { 54 float fx=normalize(x); 55 float fy=normalize(y); 56 //(x,y) (-x,-y) (-x,y) (x,-y) 57 glVertex2f(fcx+fx,fcy+fy); 58 glVertex2f(fcx-fx,fcy-fy); 59 glVertex2f(fcx-fx,fcy+fy); 60 glVertex2f(fcx+fx,fcy-fy); 61 62 //(y,x) (-y,-x) (-y,x) (y,-x) 63 glVertex2f(fcx+fy,fcy+fx); 64 glVertex2f(fcx-fy,fcy-fx); 65 glVertex2f(fcx-fy,fcy+fx); 66 glVertex2f(fcx+fy,fcy-fx); 67 68 if(d<0) { 69 d=d+2*x+3; 70 } else { 71 d=d+2*(x-y)+5; 72 --y; 73 } 74 ++x; 75 } 76 //need the 4 points on the diagonal 77 float diagonal=float(r)/sqrt(2); 78 glVertex2f(fcx+diagonal,fcy+diagonal); 79 glVertex2f(fcx-diagonal,fcy+diagonal); 80 glVertex2f(fcx+diagonal,fcy-diagonal); 81 glVertex2f(fcx-diagonal,fcy+diagonal); 82 83 x=0; 84 y=r; 85 86 87 glEnd();
简单说一下在代码最初的调试更改出现过一些什么弱智问题。
当输入圆心不是原点的时候,整个圆就支离破碎裂成了好几块,裂出的圆弧位置还不一样。调试了半天发现原来是对称那部分出了问题。把该加上fy的部分和fx的部分写反了(……)。
62 //(y,x) (-y,-x) (-y,x) (y,-x)63 glVertex2f(fcx+fy,fcy+fx);64 glVertex2f(fcx-fy,fcy-fx);65 glVertex2f(fcx-fy,fcy+fx);66 glVertex2f(fcx+fy,fcy-fx);
还有就是圆看起来不够圆,像个椭圆。其实就是应该把窗口尺寸调整到长宽一致的正方形就好了(……),因为长宽尺寸不一致的话x轴和y轴的单位长度就不一样嘛。
另外就是绘制好了之后用鼠标调整窗口尺寸或者放大后,图形就消失了(——!)。对照没这个问题的线段绘制代码看了半天,原来是为了保持窗口一直显示图形,glBegin()和glEnd()之间的代码会反复循环地绘制直到窗口关闭。所以在glEnd()前要重新给x和y赋初值,不然后面就绘制不出来了。这个我以为已经改好了,刚才试着跑了一下发现交了作业的代码忘记改这个了(——!),所以临时加上去了给x和y赋初值的代码。不知道为什么看起来圆的线条粗了一些,唉不想讨论了就让往事随风(……)。
结果展示
转载于:https://www.cnblogs.com/RDaneelOlivaw/p/6624927.html
OpenGL光栅化作业:【bresenham算法】GL_POINTS为基础画圆相关推荐
- 掌握一种基本图形元素光栅化算法,利用OpenGL实现直线光栅化的DDA算法。
一.任务描述 根据下面要求,在右侧修改代码,绘制出预期输出的图片.平台会对你编写的代码进行测试. 1.本关任务 掌握一种基本图形元素光栅化算法,利用OpenGL实现直线光栅化的DDA算法. 2.预期输 ...
- 圆的Bresenham算法C语言代码,圆的Bresenham算法的opengL实现
源代码实现如下: // Bresenham_circile.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include #includ ...
- 计算机图形学笔记五:光栅化(消隐算法)和 前几节内容总结
消隐算法和前几节内容总结 1.消隐算法 1.1画家算法(Painter's Algorithm) 1.2 Z-Buffer算法 2.前几节内容总结 1.消隐算法 1.1画家算法(Painter's A ...
- openGL实现中点画线算法、DDA画线算法,Bresenham画线算法,并进行鼠标键盘的交互
首先设置变量用于进行鼠标交互和键盘交互: int m = 0; GLdouble m1 =0, m2 = 0; 1.实验入口主函数: //主函数 int main(int argc, char** a ...
- matlab八分之一中点画圆算法,中点八分画圆算法
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 #include #include #define W 800 #define H 600 void drawCircle(SDL_Renderer* r ...
- 第一次OpenCV小作业-使用鼠标左键画圆画矩形
2020年9月28日 OpenCV中GUI的特性作业: 在白色(255, 255, 255)的背景中,利用滑动条选择颜色(RGB!),用鼠标左键画圆,右键画矩形. 分析: 要在白色背景中,利用滑动条选 ...
- 直线的Bresenham算法c语言,Bresenham算法
上回说到, 在看一本书<Windows游戏编程大师技巧> (Tricks of Windows Game Programming Gurus). 这次继续书里的内容: 直线光栅化的Bres ...
- 【计算机图形学】基于OpenGL的中点Bresenham算法画直线
学习过三种画直线的方法(DDA.中点Bresenham算法.改进的中点Bresenham算法)后,想着实际操作一下如何能够实现,OpenGL无疑是很好的选择,在老师的推荐下,我尝试着用OpenGL来实 ...
- 计算机图形学(光栅显示系统、基于GLUT的OpenGL程序框架、基本图元光栅化)
1.光栅显示系统 图形显示设备–CRT光栅扫描显示器(阴极射线管显示器) 电子束轰击屏幕表面的荧光物质,从而产生不同亮度的光点,这些光点是显示器可以控制的最小单位,称为像素.光点会逐渐变暗,需要不断刷 ...
- 图形学学习笔记2——点阵图形光栅化
点阵图形光栅化 将参数描述的图形转化为点阵的算法,评价指标有:精度.时间复杂度.空间复杂度.对实时性要求高的实时渲染场景比如游戏动画,应该需要更快的转化为点阵.类似制作动画片的离线渲染就对精度要求更高 ...
最新文章
- C++拾取——使用stl标准库生成等差、等比数列的方法
- nginx正向代理和反正代理区别
- 浏览器插件 火狐插件
- ELK集群的搭建和Elasticsearchd api的简单使用
- 全球隔夜主要金融市场回顾
- DL之DeepLabv3:DeepLab v3和DeepLab v3+算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
- python tkinter画布位置_Python Tkinter坐标画布
- iptables详解以及企业常用案例
- [Reverse] - 百度杯”CTF比赛 2017 二月场-CrackMe-1
- LeetCode 2001. 可互换矩形的组数
- minio 并发数_MinIO 参数解析与限制
- 关于oracle的物理dg,oracle物理DG管理-redo数据传输,应用与三种模式
- (转)淘淘商城系列——展示后台管理页面
- Java Swing Mysql学生选课系统
- 程序员又迎一利器,联想 LeapIOT 工业互联网平台大曝光
- jQuery Live Query 插件
- pytorch 学习1
- poj 2195(KM求最小权匹配)
- 塑料成型计算机模拟技术,塑料成型模拟软件技术基础与应用
- Termux安装SSH,下载linux系统
热门文章
- 汽车冬季养护的四个重点
- mysql数据库character_关于MySQL如何修改character
- 阿兹尔海默症生物标志物(姑且叫标志物)的一些总结
- (转载)费玉清生活清贫 是低调大富翁
- 计算机硬盘用u盘维修,电脑维修:U盘和移动硬盘及固态硬盘的区别
- atom 64 linux,英特尔:Android的64位Atom处理器已完工
- 使用Apache搭建Web网站服务器
- 【集合论】等价关系个数计算问题 ( 有序对个数计算 | 二元关系个数计算 | 划分 | 等价关系 )
- 微信小程序--个人主页的制作
- 虚拟服务器443端口开启,服务器开启443端口