2011-09-20 26 views
10

Tengo un conjunto de puntos y cada uno tiene un área de "influencia" o esencialmente un radio. Me gustaría poder dibujar cada uno de estos círculos de influencia para todos los puntos como una simple línea circular.Dibujo del contorno de los círculos que se cruzan

Se superponen, sin embargo, deseo dibujar el exterior de la forma formada. Sé que esto probablemente me requeriría trabajar donde se cruzan y de alguna manera formando una forma total para dibujar. ¡El problema es que algunos puntos ni siquiera pueden tocar a otros! Así que necesito poder resolver eso también.

he tratado de ilustrar lo que quiero decir simplemente:

enter image description here

Tenga en cuenta que deseo llamar simplemente la línea de negro, sin relleno. Esto se debe a que deseo que se muestren las imágenes de fondo y otras geometrías.

Haría esto en OpenGL, así que el círculo probablemente se haría usando GL_LINES o algo así como con varios vértices formando las curvas, pero realmente no tengo idea de cómo funcionaría este perímetro.

¡Si alguien tiene algún consejo o podría indicarme cómo podría trabajar en esto, sería muy apreciado!

Esto podría ser más una cuestión de matemáticas, no estoy buscando bits de código, pero en realidad la forma de trabajar estas formas. ¡No puedo pensar en cómo hacerlo!

***** Edit: con la solución que se me ocurrió, ¡con suerte podría ayudar a alguien más!

Así que utilicé las ideas sugeridas y básicamente decidí que la mejor manera sería dibujar usando el buffer de esténcil. Esto ahora significa que recorro mis puntos 3 veces, pero necesito hacer una cuidadosa selección de ellos para encontrar solo los visibles de todos modos.

Así código sabia ahora tengo esto:

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

Mis puntos están en entidades esencia llamada "estrellas" a los efectos de mi programa y StarOb es una colección de quads he cargado desde un archivo que se forman un lindo y suave circulo

Desactivo la máscara de color y realizo un bucle una vez, dibujando el círculo más grande que puedo en el búfer del esténcil y estableciendo un valor de 1. Luego vuelvo a dibujar dibujando el círculo más pequeño en el búfer del esténcil pero esta vez configurando valor de 0. Esto debería dejar un borde alrededor de cualquier estrella que no toque otras estrellas y eliminará efectivamente donde se superponen.

Finalmente vuelvo a habilitar la máscara de color y dibujo los círculos de color. ¡el buffer de la plantilla evita que el interior se reproduzca y obtengo lo que quería! Luego desactivo el buffer de esténcil.

Si realmente quería verlo, aquí hay un video de la generación de varias cantidades cada vez mayores de puntos: Video of it running

que aquí hay una versión de baja calidad de la forma en que salió (de fondo no se ha elaborado durante la prueba):

Overlapping circles with centre not drawn due to stencil

Respuesta

6

Primero, imagine que el fondo no estaba allí. Estoy bastante seguro de que sabría cómo hacerlo, dibujar cada círculo y luego dibujar sus interiores (como en un círculo relleno) para eliminar los arcos que están dentro.

Ahora, para hacer lo mismo con una imagen, puede hacer cualquiera de estas cosas. Una cosa que puede hacer es desactivar la escritura en el búfer de color, hacer ese procedimiento y cambiar el búfer de esténcil. A continuación, habilite la escritura en el búfer de color y dibuje un rectángulo de pantalla completa que llene los píxeles que ha marcado en el búfer del esténcil.

Sin embargo, es posible que el búfer de plantilla no se pueda utilizar por un par de razones, como por ejemplo, si lo está utilizando para otra cosa. En este caso, una alternativa sería hacer lo mismo, pero en lugar de renderizar en el buffer de esténcil, se renderiza en una textura. Luego une esa textura y dibuja un rectángulo en la pantalla.

Estoy bastante seguro de que podría lograr esto con el buffer de acumulación también, pero nunca he usado, así que no puedo realmente decir (si alguien sabe de eso, por favor editar mi respuesta y nos dicen cómo)

+0

Gracias por su sugerencia. He logrado hacerlo con el buffer de esténcil y volví a actualizar mi pregunta con mi solución, que es un poco lo que sugería. ¡No estoy seguro de a quién debería marcar ahora! – iexus

+1

¿Tal vez nos dé a los dos un +1? : D – Shahbaz

+0

Hecho: D He actualizado mi pregunta para mostrar con qué terminé.¿Era ese el tipo de manera en que estabas pensando? Me falta un poco de conocimiento opengl ... – iexus

3

Dos pases:

  1. atraer a todos a través de su círculo esboza GL_LINES o GL_LINE_LOOP. Asegúrese de configurar glLineWidth() en 3 o superior.
  2. lleno dibujar círculos (GL_TRIANGLE_STRIP puede ser útil) con su "fondo" color y el mismo radio que los círculos desde el paso 1.

Los círculos rellenos en el paso 2 sobrescribirá todos los píxeles de contorno de la etapa 1 pero solo donde se superponen Eso te deja intactos los contornos que no se superponen.

Si desea un mayor rango de ancho de contorno (es decir, mayor que ~ 10 que la mayoría de las implementaciones OpenGL permiten glLineWidth()) debe reutilizar el representador de círculo relleno del paso 2 en el paso 1, excepto con un radio mayor.

+0

La razón por la que quería dibujar el contorno era permitir que se mostrara una imagen de fondo (y también varias capas/entidades dibujadas previamente). Si renuncio a eso, ¡esta sería la primera elección que habría hecho! – iexus

+2

Utilizaría el procedimiento anterior, pero dibujaré los círculos en el búfer del esténcil y habilitaré la prueba del búfer del esténcil al dibujar el resto de su geometría. –

+0

Ah, seré honesto, no había pensado en eso. No estoy muy familiarizado con él, así que leeré un poco. Supongo que haces algo así como, dibuja el círculo más grande de un cierto color/valor en el esténcil y el más pequeño a uno diferente también en el esténcil. Si el valor de la prueba de esténcil es el valor grande, colorea el fragmento y si no, ¿no haces nada? – iexus

Cuestiones relacionadas