2011-09-20 10 views
10

Mam zestaw punktów i każdy ma obszar "wpływu" lub zasadniczo promień. Chciałbym móc narysować każdy z tych okręgów wpływów dla wszystkich punktów jako prostą okrągłą linię.Obrys rysunku przecinających się okręgów

Będą zachodzić na siebie, ale chcę narysować zewnętrzną stronę utworzonego kształtu. Wiem, że to prawdopodobnie wymagałoby pracy nad tym, gdzie przecinają się i w jakiś sposób tworząc całkowitą formę do narysowania. Problem polega na tym, że niektóre punkty mogą nawet nie dotykać innych! Muszę też umieć to wypracować.

starałem się zilustrować, co mam na myśli po prostu:

enter image description here

Zauważ, że pragnę zwrócić po prostu czarną linię, bez wypełnienia. Dzieje się tak, ponieważ chciałbym pokazać obrazy tła i inną geometrię.

Zrobiłbym to w OpenGL, więc koło byłoby prawdopodobnie wykonane przy użyciu GL_LINES lub niektórych z różnymi wierzchołkami tworzącymi krzywe, ale tak naprawdę po prostu nie mam pojęcia o tym, jak mógłbym obliczyć ten obwód.

Jeśli ktoś ma jakąkolwiek radę lub może wskazać mi, w jaki sposób mogę to wypracować, byłbym bardzo wdzięczny!

To może być bardziej pytanie matematyczne, nie szukam fragmentów kodu, ale tak naprawdę, jak pracować nad tymi kształtami. Po prostu nie mogę myśleć o tym, jak to zrobić!

***** Edytuj: dzięki rozwiązaniu, które wymyśliłem, mam nadzieję, że pomogę komuś innemu!

Więc użyłem sugerowanych pomysłów i zasadniczo zdecydowałem, że najlepiej będzie narysować za pomocą bufora szablonu. Oznacza to teraz, że przechodzę przez moje punkty 3 razy, ale muszę je ostrożnie sortować, aby znaleźć tylko widoczne.

Więc kod mądry teraz mam to:

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

Moje punkty są w jednostkach istocie zwane „gwiazdy” dla celów moim programie i StarOb jest zbiorem quadów Mam ładowane z pliku, który formularz ładne, gładkie koło.

Wyłączam maskę kolorów i przepuszczam jeden raz, rysując największy krąg, jaki mogę w buforze szablonowym i ustawiając wartość 1. Pętla znowu rysuję mniejszy, skalowany okrąg w buforze szablonu, ale tym razem ustawienie wartość 0. Powinno to zostawiać obramowanie wokół dowolnej gwiazdy, która nie dotyka innych gwiazd i skutecznie usunąć tam, gdzie się pokrywają.

W końcu ponownie włączam maskę kolorów i rysuję kolorowe kółka. bufor szablonów zatrzymuje renderowanie stron i otrzymuję to, co chcę! Następnie wyłączam bufor szablonu.

Jeśli naprawdę chciał go zobaczyć, oto wideo generowania kilka rosnących ilości punktów: Video of it running

Oto wersja niska jakość jak wyszło (tło nie został sporządzony podczas testowania):

Overlapping circles with centre not drawn due to stencil

Odpowiedz

6

Najpierw wyobraź sobie, że nie było tła. Jestem pewien, że wiesz, jak to zrobić, narysuj każdy okrąg, a następnie narysuj jego wnętrze (jak w wypełnionym kole), aby usunąć łuki, które są w środku.

Teraz, aby zrobić to samo z obrazem, można zrobić jedną z tych rzeczy. Jedną z rzeczy, które możesz zrobić, to wyłączyć zapisywanie w buforze kolorów, wykonać tę procedurę i zmienić bufor szablonu. Następnie włącz zapisywanie w buforze kolorów i narysuj cały ekran, co spowoduje wypełnienie pikseli zaznaczonych w buforze szablonu.

Bufor szablonów może nie być dla Ciebie użyteczny, ale z kilku powodów, na przykład gdy używasz go do czegoś innego. W takim przypadku alternatywą byłoby zrobienie tego samego, ale zamiast renderowania w buforze szablonu renderujesz teksturę. Następnie połącz tę strukturę i narysuj prostokąt na ekranie.

Jestem prawie pewien, że można to osiągnąć również z buforem akumulacyjnym, ale nigdy go nie użyłem, więc nie mogę powiedzieć (jeśli ktoś o tym wie, edytuj moją odpowiedź i powiedz nam jak to zrobić)

+0

Dziękuję za sugestię, że udało mi się to zrobić przy użyciu bufora szablonu i wróciłem, aby zaktualizować moje pytanie za pomocą mojego rozwiązania, które jest czymś, co sugerujesz. Nie jestem pewien, kogo mam teraz zaznaczyć! – iexus

+1

Może dać nam obu +1? : D – Shahbaz

+0

Zrobione: D Zaktualizowałem moje pytanie, aby pokazać, co doprowadziło mnie do skutku.Czy tak właśnie myślałeś? Trochę brakuje mi wiedzy na temat OpenGL .. – iexus

3

Dwa karnety:

  1. przyciągnę wszystkich kręgu kontury poprzez GL_LINES lub GL_LINE_LOOP. Upewnij się, że ustawiłeś swój numer glLineWidth() na glLineWidth() na glLineWidth().
  2. Draw wypełnione kółka (GL_TRIANGLE_STRIP może być przydatne) ze swoim „czerwony” barwy i tym samym promieniu jak kręgi od kroku 1.

Napełnione okręgi w kroku 2 zastąpi wszystkie zarys pikseli z etapu 1 ale tylko tam, gdzie się pokrywają. Pozostawia to nienaruszone niezachodzące na siebie kontury.

Jeśli chcesz szerszy zakres szerokości obrysu (tj. Większy niż ~ 10, że większość implementacji OpenGL zezwala na glLineWidth()), powinieneś ponownie użyć renderer z wypełnieniem z okręgu od kroku 2 z wyjątkiem większego promienia.

+0

Powodem, dla którego chciałem tylko narysować kontur, było umożliwienie przejrzenia obrazu tła (a także różnych warstw/wcześniej narysowanych obiektów). Jeśli się na tym pogodzę, to byłby to pierwszy wybór, który podjąłbym! – iexus

+2

Użyłbym powyższej procedury, ale narysuj kółka do bufora szablonu i włącz testowanie bufora szablonu podczas rysowania reszty geometrii. –

+0

Ah, będę szczery, że o tym nie pomyślałem. Nie jestem zbyt obeznana z tym, więc trochę popracuję. Zakładam, że robisz coś takiego, narysuj większy okrąg w pewnym kolorze/wartości w szablonie, a mniejszy w inny szablon również w szablonie. Jeśli wartość podczas testowania szablonów to duża wartość, to koloruj fragment, a jeśli nie, to nic nie rób? – iexus

Powiązane problemy