2011-09-20 161 views
10

我有一組點,每一個都有一個「影響」區域或基本上是一個半徑。我希望能夠將所有點的這些影響圈中的每一個畫成簡單的圓形線。交叉圓的繪製輪廓

它們會重疊,但我希望繪製所形成的形狀的外部。我知道這可能需要我確定它們相交的地方,並以某種方式形成一個完整的形狀來繪製。問題是有些點甚至可能不會觸及別人!所以我需要能夠解決這個問題。

我試圖說明我的意思只是:

enter image description here

注意,我想簡單地畫黑線,無填充。這是因爲我希望背景圖像和其他幾何圖形能夠透過。

我會在openGL中這樣做,所以圓形可能會使用GL_LINES或其他一些形成曲線的各種頂點,但我真的不知道如何解決這個問題。

如果任何人有任何建議,或可以指出我如何可能去工作,這將不勝感激!

這可能是一個數學問題的更多,我不是在尋找一些代碼,但實際上如何去做出這些形狀。我無法思考如何去做!

*****編輯:與我想出的解決方案,希望可以幫助別人!

因此,我使用了建議的想法,並基本上決定最好的方法是繪製使用模板緩衝區。這現在意味着我循環了3次我的觀點,但我需要對它們進行一些仔細的分類,以便只找到可見的分類。

所以代碼明智我現在有這樣的:

private void stencilCircleAroundStars() 
{ 
    //Lets try and draw something here using stencil 
    glColorMask(false, false, false, false); //Disable colour mask 
    glEnable(GL_STENCIL_TEST); // Enable Stencil Buffer For "marking" the outer circle 
    glDisable(GL_DEPTH_TEST);// Disable Depth Testing 

    for (Object value : stars.values()) 
    { 
     Star star = (Star)value; 

     glStencilFunc(GL_ALWAYS, 1, 1); // Always Passes, 1 Bit Plane, 1 As Mask 
     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // We Set The Stencil Buffer To 1 Where We Draw Any Polygon 

     //Draw the large circle 
     starOb.location.copy(star.location); 
     starOb.setScale(2000); 
     starOb.draw(); 
    } 

    for (Object value : stars.values()) 
    { 
     Star star = (Star)value; 
     //Now we change the functions and remove a slightly smaller circle from buffer. 
     glStencilFunc(GL_ALWAYS, 0, 0); // Always passes, 0 bit plane, 0 as mask; 
     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // We Set The Stencil Buffer To 0 Where We Draw Any Polygon 
     starOb.location.copy(star.location); 
     starOb.setScale(1900); 
     starOb.draw(); 
    } 

    //Now we enable the colour 
    glColorMask(true, true, true, true); 
    glStencilFunc(GL_EQUAL, 1, 1); // We Draw Only Where The Stencil Is 1 
    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // Don't Change The Stencil Buffer 

    glColor4f(0.5f, 1.0f, 0.5f, 0.5f); 
    for (Object value : stars.values()) 
    { 
     Star star = (Star)value; 
     starOb.location.copy(star.location); 
     starOb.setScale(2000); 
     starOb.draw(); 
    } 

    //Now we are done .. disable 
    glDisable(GL_STENCIL_TEST); 
} 

我點是所謂的「明星」爲我計劃的目的和StarOb是四邊形的集合,我已經從一個文件,該文件的形式加載本質實體一個不錯的光滑圓圈。

我禁用了顏色遮罩,我循環了一次,將最大的圓圈插入模板緩衝區並將值設置爲1.然後,再次循環繪製較小的縮放圓圈到模板緩衝區,但是這次設置值爲0.這應該在任何未接觸其他恆星的恆星周圍留下邊界,並且將有效地消除它們重疊的地方。

我終於重新啓用顏色蒙版,並實際繪製彩色圓圈。模板緩衝區停止渲染內部,我得到我想要的!然後我禁用模板緩衝區。

如果你真的想看到它,這裏的生成點幾越來越多的視頻:Video of it running

這裏是它如何出來(背景不同時測試得出)低質量版本:

Overlapping circles with centre not drawn due to stencil

回答

6

首先,想象背景不在那裏。我很確定你會知道如何去做,繪製每個圓,然後繪製它們的內側(如實心圓)以去除裏面的圓弧。

現在要對圖像做同樣的事情,你可以做這些事情。你可以做的一件事是禁止在顏色緩衝區上寫入,執行該過程並更改模板緩衝區。然後啓用在顏色緩衝區中寫入並繪製一個完整的屏幕矩形,從而填充您在模板緩衝區中標記的像素。

模板緩衝區可能不適用於您,但有幾個原因,例如您正在使用它來做其他事情。在這種情況下,替代方法是做同樣的事情,但不是在模具緩衝區中渲染,而是渲染紋理。然後綁定該紋理並在屏幕上繪製一個矩形。

我相當肯定,你可以用積累緩衝器也做到這一點,但我從來沒有使用過它,所以我真的不能告訴(如果任何人知道這件事,請編輯我的答案,告訴我們如何)

+0

感謝您的建議我已經設法使用模板緩衝區來解決問題,然後回來用我的解決方案更新我的問題,這是您建議的。不知道我現在應該打勾! – iexus

+1

也許給我們兩個+1? :D – Shahbaz

+0

完成:D我已經更新了我的問題,以顯示最終結果。那是你想的那種方式嗎?我有點缺乏opengl知識.. – iexus

3

二遍:

  1. 畫出你所有的圈子概述通過GL_LINESGL_LINE_LOOP。確保您將glLineWidth()設置爲3或更高。
  2. 繪圖實心圓圈(GL_TRIANGLE_STRIP可能是有用的)與「背景」的顏色和相同的半徑的圓圈從步驟1

在步驟2中的實心圓將覆蓋所有的輪廓象素從步驟1但只在它們重疊的地方。這會讓你保持不重疊的輪廓。

如果您想要更寬範圍的輪廓寬度(即大於大多數OpenGL實現允許的最大值〜10),則應在步驟1中重複使用步驟2中的實心圓渲染器,但半徑較大。

+0

我只想繪製輪廓的原因是允許背景圖像(以及各種圖層/先前繪製的實體)通過。如果我放棄這一點,那麼這將是我會做的第一選擇! – iexus

+2

我會使用上面的過程,但是畫圓圈到模板緩衝區,並且在繪製剩餘的幾何圖形時啓用模板緩衝區測試。 –

+0

啊我說實話我沒有想到這一點。我不是很熟悉,所以我會做一些閱讀。我假設你做了類似的事情,將較大的圓圈繪製成模板,將較小的圓圈繪製成模板中的另一種顏色/值。如果模板測試時的值是largeValue,那麼給片段着色,如果不是,那麼什麼都不做? – iexus