日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

OpenGL光栅化作业:【bresenham算法】GL_POINTS为基础画圆

發(fā)布時(shí)間:2023/12/16 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenGL光栅化作业:【bresenham算法】GL_POINTS为基础画圆 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

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.

嘛,所以其實(shí)也是跟前面畫線段的算法一樣,也是用GL_POINTS畫出足夠多且密集的離散點(diǎn)在視覺(jué)意義上產(chǎn)生一個(gè)圓形。有很多類似的地方,控制輸入范圍為[-500,500]區(qū)間的整數(shù)再規(guī)格化到[-1,1]的浮點(diǎn)數(shù)等等,這些分析,就不廢話了直接看前面那篇講畫線段的前半截就好。

由于在畫圓方面沒(méi)有什么思路,所以參考了一下網(wǎng)上的畫圓算法。注明參考出處:http://www.cnblogs.com/gamesky/archive/2012/09/03/2668932.html

并且

由于數(shù)學(xué)確實(shí)差(……)所以也沒(méi)有做算法推導(dǎo),直接用了以上這篇博文推導(dǎo)出的結(jié)論。也就是:

【先假設(shè)圓心的坐標(biāo)為原點(diǎn)】。

先算出從(0, r)到(r/√2,?r/√2)之間的1/8圓弧的點(diǎn)的坐標(biāo)值,其他部分直接用軸對(duì)稱和中心對(duì)稱變換,最后畫出完整的圓形。

也就是計(jì)算出那特定的1/8圓弧上的點(diǎn)的坐標(biāo)(x,y),再繪制出相應(yīng)的(x, -y), (-x, y), (-x, -y), (y, x), (-y, x), (y, -x), (-y, -x)。

?

而那1/8圓弧上因?yàn)閤上的變化比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()之間用一個(gè)while(y>x)的循環(huán),繪制出(x,y)和它相應(yīng)的對(duì)稱點(diǎn)就好,也不需要用畫線段時(shí)導(dǎo)入數(shù)組的辦法了(畢竟哪里一不小心就下標(biāo)越界還占內(nèi)存orz)。當(dāng)然這里在調(diào)用glVertex的時(shí)候傳入的參數(shù)(1)首先要是浮點(diǎn)數(shù),所以仍然要做一個(gè)規(guī)格化處理normalize()。(2)要考慮到圓心坐標(biāo)其實(shí)未必是原點(diǎn)的情況,對(duì)得到的浮點(diǎn)數(shù)坐標(biāo)還要做一個(gè)浮點(diǎn)圓心坐標(biāo)(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圓弧和與其對(duì)稱的圓弧之外,我發(fā)現(xiàn)這樣寫其實(shí)沒(méi)有考慮到x=y,x=-y的點(diǎn)的情況。雖然這樣圓看起來(lái)也沒(méi)什么影響,但由于強(qiáng)迫癥,所以還是加上一段:

//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);

不過(guò)我想了一下,在前面的while循環(huán)判斷條件改成y>=x可能就好了,雖然可能會(huì)出現(xiàn)重復(fù)繪制的情況(……),不過(guò)寫都寫了就這樣吧呵呵呵呵呵呵呵

?

然后如果看了前面那篇參考博文的內(nèi)容,其他反正都挺好懂的就不講廢話了直接上完全代碼。

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();

?

簡(jiǎn)單說(shuō)一下在代碼最初的調(diào)試更改出現(xiàn)過(guò)一些什么弱智問(wèn)題。

當(dāng)輸入圓心不是原點(diǎn)的時(shí)候,整個(gè)圓就支離破碎裂成了好幾塊,裂出的圓弧位置還不一樣。調(diào)試了半天發(fā)現(xiàn)原來(lái)是對(duì)稱那部分出了問(wèn)題。把該加上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);

還有就是圓看起來(lái)不夠圓,像個(gè)橢圓。其實(shí)就是應(yīng)該把窗口尺寸調(diào)整到長(zhǎng)寬一致的正方形就好了(……),因?yàn)殚L(zhǎng)寬尺寸不一致的話x軸和y軸的單位長(zhǎng)度就不一樣嘛。

?

另外就是繪制好了之后用鼠標(biāo)調(diào)整窗口尺寸或者放大后,圖形就消失了(——!)。對(duì)照沒(méi)這個(gè)問(wèn)題的線段繪制代碼看了半天,原來(lái)是為了保持窗口一直顯示圖形,glBegin()和glEnd()之間的代碼會(huì)反復(fù)循環(huán)地繪制直到窗口關(guān)閉。所以在glEnd()前要重新給x和y賦初值,不然后面就繪制不出來(lái)了。這個(gè)我以為已經(jīng)改好了,剛才試著跑了一下發(fā)現(xiàn)交了作業(yè)的代碼忘記改這個(gè)了(——!),所以臨時(shí)加上去了給x和y賦初值的代碼。不知道為什么看起來(lái)圓的線條粗了一些,唉不想討論了就讓往事隨風(fēng)(……)。

?

結(jié)果展示

?

?

轉(zhuǎn)載于:https://www.cnblogs.com/RDaneelOlivaw/p/6624927.html

總結(jié)

以上是生活随笔為你收集整理的OpenGL光栅化作业:【bresenham算法】GL_POINTS为基础画圆的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。