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为基础画圆相关推荐

  1. 掌握一种基本图形元素光栅化算法,利用OpenGL实现直线光栅化的DDA算法。

    一.任务描述 根据下面要求,在右侧修改代码,绘制出预期输出的图片.平台会对你编写的代码进行测试. 1.本关任务 掌握一种基本图形元素光栅化算法,利用OpenGL实现直线光栅化的DDA算法. 2.预期输 ...

  2. 圆的Bresenham算法C语言代码,圆的Bresenham算法的opengL实现

    源代码实现如下: // Bresenham_circile.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include #includ ...

  3. 计算机图形学笔记五:光栅化(消隐算法)和 前几节内容总结

    消隐算法和前几节内容总结 1.消隐算法 1.1画家算法(Painter's Algorithm) 1.2 Z-Buffer算法 2.前几节内容总结 1.消隐算法 1.1画家算法(Painter's A ...

  4. openGL实现中点画线算法、DDA画线算法,Bresenham画线算法,并进行鼠标键盘的交互

    首先设置变量用于进行鼠标交互和键盘交互: int m = 0; GLdouble m1 =0, m2 = 0; 1.实验入口主函数: //主函数 int main(int argc, char** a ...

  5. matlab八分之一中点画圆算法,中点八分画圆算法

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 #include #include #define W 800 #define H 600 void drawCircle(SDL_Renderer* r ...

  6. 第一次OpenCV小作业-使用鼠标左键画圆画矩形

    2020年9月28日 OpenCV中GUI的特性作业: 在白色(255, 255, 255)的背景中,利用滑动条选择颜色(RGB!),用鼠标左键画圆,右键画矩形. 分析: 要在白色背景中,利用滑动条选 ...

  7. 直线的Bresenham算法c语言,Bresenham算法

    上回说到, 在看一本书<Windows游戏编程大师技巧> (Tricks of Windows Game Programming Gurus). 这次继续书里的内容: 直线光栅化的Bres ...

  8. 【计算机图形学】基于OpenGL的中点Bresenham算法画直线

    学习过三种画直线的方法(DDA.中点Bresenham算法.改进的中点Bresenham算法)后,想着实际操作一下如何能够实现,OpenGL无疑是很好的选择,在老师的推荐下,我尝试着用OpenGL来实 ...

  9. 计算机图形学(光栅显示系统、基于GLUT的OpenGL程序框架、基本图元光栅化)

    1.光栅显示系统 图形显示设备–CRT光栅扫描显示器(阴极射线管显示器) 电子束轰击屏幕表面的荧光物质,从而产生不同亮度的光点,这些光点是显示器可以控制的最小单位,称为像素.光点会逐渐变暗,需要不断刷 ...

  10. 图形学学习笔记2——点阵图形光栅化

    点阵图形光栅化 将参数描述的图形转化为点阵的算法,评价指标有:精度.时间复杂度.空间复杂度.对实时性要求高的实时渲染场景比如游戏动画,应该需要更快的转化为点阵.类似制作动画片的离线渲染就对精度要求更高 ...

最新文章

  1. C++拾取——使用stl标准库生成等差、等比数列的方法
  2. nginx正向代理和反正代理区别
  3. 浏览器插件 火狐插件
  4. ELK集群的搭建和Elasticsearchd api的简单使用
  5. 全球隔夜主要金融市场回顾
  6. DL之DeepLabv3:DeepLab v3和DeepLab v3+算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
  7. python tkinter画布位置_Python Tkinter坐标画布
  8. iptables详解以及企业常用案例
  9. [Reverse] - 百度杯”CTF比赛 2017 二月场-CrackMe-1
  10. LeetCode 2001. 可互换矩形的组数
  11. minio 并发数_MinIO 参数解析与限制
  12. 关于oracle的物理dg,oracle物理DG管理-redo数据传输,应用与三种模式
  13. (转)淘淘商城系列——展示后台管理页面
  14. Java Swing Mysql学生选课系统
  15. 程序员又迎一利器,联想 LeapIOT 工业互联网平台大曝光
  16. jQuery Live Query 插件
  17. pytorch 学习1
  18. poj 2195(KM求最小权匹配)
  19. 塑料成型计算机模拟技术,塑料成型模拟软件技术基础与应用
  20. Termux安装SSH,下载linux系统

热门文章

  1. 汽车冬季养护的四个重点
  2. mysql数据库character_关于MySQL如何修改character
  3. 阿兹尔海默症生物标志物(姑且叫标志物)的一些总结
  4. (转载)费玉清生活清贫 是低调大富翁
  5. 计算机硬盘用u盘维修,电脑维修:U盘和移动硬盘及固态硬盘的区别
  6. atom 64 linux,英特尔:Android的64位Atom处理器已完工
  7. 使用Apache搭建Web网站服务器
  8. 【集合论】等价关系个数计算问题 ( 有序对个数计算 | 二元关系个数计算 | 划分 | 等价关系 )
  9. 微信小程序--个人主页的制作
  10. 虚拟服务器443端口开启,服务器开启443端口