2008-09-19 53 views

Trả lời

1

Giả sử điểm ban đầu của bạn là (x1, y1) -> (x2, y2). Sử dụng các điểm sau (x1-width/2, y1), (x1 + width/2, y1), (x2-width/2, y2), (x2 + width/2, y2) để tạo hình chữ nhật và sau đó sử dụng quads/tris để vẽ nó. Đây là cách ngây thơ đơn giản. Lưu ý rằng đối với chiều rộng dòng lớn, bạn sẽ nhận được hành vi điểm cuối kỳ lạ. Những gì bạn thực sự muốn làm sau đó là một số tính toán đường song song thông minh (mà không nên là xấu) bằng cách sử dụng toán học vector. Đối với một số lý do dot/cross sản phẩm và chiếu vector đến tâm trí.

+0

@Ozgur 's câu trả lời là tốt hơn nhiều. Cân nhắc việc thêm phép tính vectơ mà bạn đang nói đến. – Valdrinit

14

Bạn có thể vẽ hai tam giác:

// 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(); 
} 
+3

Đây là cách quá phức tạp! Quá nhiều lượng giác, nơi nó không cần thiết quá. – PierreBdR

+0

Hóa ra đây không phải là những gì OP muốn (xem câu trả lời của mình dưới đây). Nhưng tôi rất muốn thấy một thuật toán đơn giản hơn, nếu bạn muốn chia sẻ nó. –

+0

Tôi đã thêm một phiên bản miễn phí trig ở đây bây giờ – bobobobo

0

Một hình chữ nhật (ví dụ: GL_QUAD hoặc hai GL_TRIANGLES) âm thanh như đặt cược tốt nhất của bạn bằng những âm thanh của nó, không chắc tôi có thể nghĩ ra cách nào khác.

9

Ok, làm thế nào về điều này: (Ozgar)

 

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

Vậy AB là width1 và CD là width2.

Sau đó,

// 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 có khả năng một CW/CCW quanh co vấn đề với thuật toán này - nếu perp được tính như (-y, x) trong sơ đồ trên thì nó sẽ uốn lượn CCW, nếu (y, -x) thì nó sẽ là một cuộn dây CW.

1

Một cách khác để làm điều này, nếu bạn đang viết một bộ quét phần mềm một cách tình cờ, là sử dụng tọa độ barycentric trong điểm ảnh màu sắc của bạn sân khấu và màu pixel khi một trong những barycentric phối là gần 0. Bạn càng kiếm được nhiều khoản trợ cấp, các dòng càng dày.

1

Tôi đã phải làm điều tương tự vào đầu ngày hôm nay.

Đối với việc tạo ra một dòng kéo dài (x1,y1) -> (x2,y2) của một width nhất định, một phương pháp rất đơn giản là để biến đổi một đơn vị có kích thước vuông đơn giản kéo dài (0., -0.5) -> (1., 0.5) sử dụng:

  1. glTranslatef(...) để di chuyển nó đến mong muốn (x1,y1) vị trí của bạn;
  2. glScalef(...) để chia tỷ lệ sang phải length và mong muốn width: sử dụng length = sqrt((x2-x1)^2 + (y2-y1)^2) hoặc bất kỳ xấp xỉ độ phức tạp thấp nào khác;
  3. glRotatef(...) đến angle theo đúng hướng: sử dụng angle = atan2(y2-y1, x2-x1).

Đơn vị vuông được tạo rất đơn giản từ dải hai tam giác GL_TRIANGLE_STRIP, biến thành dòng liền mạch của bạn sau các phép biến đổi ở trên.

Gánh nặng ở đây được đặt chủ yếu vào OpenGL (và phần cứng đồ họa của bạn) thay vì mã ứng dụng của bạn. Quy trình trên được chuyển rất dễ dàng thành một hàm chung bằng các cuộc gọi xung quanh glPushMatrix()glPopMatrix().

2

Đối với những người đang tìm kiếm giải pháp tốt cho điều này, mã này được viết bằng LWJGL, nhưng có thể dễ dàng thích nghi với bất kỳ triển khai OpenGL nào.

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(); 
} 
Các vấn đề liên quan