Pergunta

O que é a melhor maneira de desenhar uma linha largura variável sem usar glLineWidth? Basta desenhar um retângulo? Várias linhas paralelas? Nenhuma das opções acima?

Foi útil?

Solução

Suponha que seus pontos originais são (x1, y1) -> (x2, y2). Utilizar os seguintes pontos (X1-largura / 2, y1), (x1 + largura / 2, y1), (x2-largura / 2, Y2), (x2 + largura / 2, Y2) para a construção de um rectângulo e, em seguida, o uso quadriláteros / tris desenhá-lo. Esta a maneira ingênua simples. Note-se que para grandes larguras de linha você vai ter comportamento endpoint estranho. O que você realmente quer fazer, então, é algumas inteligentes cálculos linha paralela (que não deve ser tão ruim) usando matemática vetor. Para alguns dot razão produto / cruz e projeção vector vêm à mente.

Outras dicas

Você pode desenhar dois triângulos:

// Draws a line between (x1,y1) - (x2,y2) with a start thickness of t1 and
// end thickness t2.
void DrawLine(float x1, float y1, float x2, float y2, float t1, float t2)
{
    float angle = atan2(y2 - y1, x2 - x1);
    float t2sina1 = t1 / 2 * sin(angle);
    float t2cosa1 = t1 / 2 * cos(angle);
    float t2sina2 = t2 / 2 * sin(angle);
    float t2cosa2 = t2 / 2 * cos(angle);

    glBegin(GL_TRIANGLES);
    glVertex2f(x1 + t2sina1, y1 - t2cosa1);
    glVertex2f(x2 + t2sina2, y2 - t2cosa2);
    glVertex2f(x2 - t2sina2, y2 + t2cosa2);
    glVertex2f(x2 - t2sina2, y2 + t2cosa2);
    glVertex2f(x1 - t2sina1, y1 + t2cosa1);
    glVertex2f(x1 + t2sina1, y1 - t2cosa1);
    glEnd();
}

Ok, e quanto a isto: (Ozgar)

       A
      / \
     /      \
    . p1        \
   /                \
  /                    D
 B -                 .p2
      -   -    -    C

Assim AB é width1 e CD é width2.

Em seguida,

// find line between p1 and p2
Vector p1p2 = p2 - p1 ;

// find a perpendicular
Vector perp = p1p2.perpendicular().normalize()

// Walk from p1 to A
Vector A = p1 + perp*(width1/2)
Vector B = p1 - perp*(width1/2)

Vector C = p2 - perp*(width2/2)
Vector D = p2 - perp*(width2/2)

// wind triangles
Triangle( A, B, D )
Triangle( B, D, C )

Note que há potencialmente um CW / CCW enrolamento problema com esse algoritmo - se perp é calculado como (Y, X) no diagrama acima, então será CCW enrolamento, se (y, -x), então será um CW enrolamento.

Para quem vem à procura de uma boa solução para isso, este código é escrito usando LWJGL, mas pode facilmente ser adaptado a qualquer implementação de OpenGL.

import java.awt.Color;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.vector.Vector2f;
public static void DrawThickLine(int startScreenX, int startScreenY, int endScreenX, int endScreenY, Color color, float alpha, float width) {

    Vector2f start = new Vector2f(startScreenX, startScreenY);
    Vector2f end = new Vector2f(endScreenX, endScreenY);

    float dx = startScreenX - endScreenX;
    float dy = startScreenY - endScreenY;

    Vector2f rightSide = new Vector2f(dy, -dx);
    if (rightSide.length() > 0) {
        rightSide.normalise();
        rightSide.scale(width / 2);
    }
    Vector2f leftSide = new Vector2f(-dy, dx);
    if (leftSide.length() > 0) {
        leftSide.normalise();
        leftSide.scale(width / 2);
    }

    Vector2f one = new Vector2f();
    Vector2f.add(leftSide, start, one);

    Vector2f two = new Vector2f();
    Vector2f.add(rightSide, start, two);

    Vector2f three = new Vector2f();
    Vector2f.add(rightSide, end, three);

    Vector2f four = new Vector2f();
    Vector2f.add(leftSide, end, four);

    GL11.glBegin(GL11.GL_QUADS);
    GL11.glColor4f(color.getRed(), color.getGreen(), color.getBlue(), alpha);
    GL11.glVertex3f(one.x, one.y, 0);
    GL11.glVertex3f(two.x, two.y, 0);
    GL11.glVertex3f(three.x, three.y, 0);
    GL11.glVertex3f(four.x, four.y, 0);
    GL11.glColor4f(1, 1, 1, 1);
    GL11.glEnd();
}

Outra maneira de fazer isso, se você estiver escrevendo um rasterizer software por acaso, é a utilização de coordenadas baricêntricas em seus pixels coloração palco e cor pixels quando uma das coordenadas baricêntricas está perto 0 . A mais de um subsídio que você faz, o mais grosso das linhas será.

Eu tive que fazer a mesma coisa hoje cedo.

Para criar uma linha que se estende por (x1,y1) -> (x2,y2) de um determinado width, um método muito fácil é transformar um simples (0., -0.5) -> (1., 0.5) spanning quadrado tamanho unidade usando:

  1. glTranslatef(...) para movê-lo para a sua localização (x1,y1) desejado;
  2. glScalef(...) escalá-lo ao length direita e width desejado: uso length = sqrt( (x2-x1)^2 + (y2-y1)^2 ) ou qualquer outra aproximação de baixa complexidade;
  3. glRotatef(...) para angle-lo para a orientação direita:. Uso angle = atan2(y2-y1, x2-x1)

A unidade-quadrado é muito simples criado a partir de um de dois triângulo tira GL_TRIANGLE_STRIP, que se transforma em sua linha sólida após as transformações acima.

A carga aqui é colocado principalmente em OpenGL (e seu hardware gráfico), em vez do código do aplicativo. O procedimento acima é ligado muito facilmente em uma função genérica cercando chamadas glPushMatrix() e glPopMatrix().

Um retângulo sons como sua melhor aposta pelos sons dele, não tenho certeza que eu posso pensar de outra maneira.

(ou seja GL_QUAD ou dois GL_TRIANGLES)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top