1)我知道箭头的起点,也知道终点。
我不知道如何画箭头的头部..我假设头部的其他两点与终点成45度角...
有人知道这样做所需的公式吗?
Wade 对于这个问题的 OpenGL 部分给出了很好的答案;我将尝试回答向量数学部分。这是我脑海中的一些伪代码:
Triangle GenerateArrowHead(vec2 p1, vec2 p2)
{
// Compute the vector along the arrow direction
vec2 v = Normalize(p2 - p1)
// Compute two perpendicular vectors to v
vec2 vPerp1 = vec2(-v.y, v.x)
vec2 vPerp2 = vec2(v.y, -v.x)
// Compute two half-way vectors
vec2 v1 = Normalize(v + vPerp1)
vec2 v2 = Normalize(v + vPerp2)
Triangle tri;
tri.a = p2;
tri.b = p2 + ArrowHeadSize * v1;
tri.c = p2 + ArrowHeadSize * v2;
return tri;
}
为什么这不起作用?
1)为头部绘制一个三角形(意思是用GL_TRIANGLES绘制,而不是绘制形成三角形的3条线段)
2) 从三角形底边的中点延伸出一条线段。
我最近实现了一个基本算法,它生成二维箭头的点并将其存储在传入的数组中,希望这可以帮助任何想要在 opengl 中创建健壮箭头的人:
/**
* \brief Create the points of an arrow pointing from one point to another
*
* g\
* | --\
* | ---\
* | a-------------------------------c --\
* stem | | -------/ | --\
* thickness | start -------/ | -----end
* | | -------/ | --/
* | b---/---------------------------d --/
* | ---/
* | --/
* f/
*
* ------tip len-------
*
* returns [a, b, c, d, e, f, g] from this we want to produce indices
*
* {a, b, c}, {c, b, d}, {e, f, g}
* {0, 1, 2}, {2, 1, 3}, {4, 5, 6}
*
* \author cuppajoeman (2024)
*/
void store_arrow_vertices(glm::vec2 start, glm::vec2 end, float stem_thickness, float tip_length, float *out_flattened_vertices) {
float half_thickness = stem_thickness / (float) 2;
glm::vec2 start_to_end = end - start;
glm::vec2 end_to_start = start - end;
float stem_length = std::max(0.0f, glm::length(start_to_end) - tip_length);
glm::vec2 start_to_end_normalized = glm::normalize(start_to_end);
glm::vec2 end_to_start_normalized = glm::normalize(end_to_start);
// note that these two are also normalized
glm::vec2 start_to_a_dir = glm::vec2(-start_to_end_normalized.y, start_to_end_normalized.x);
glm::vec2 start_to_b_dir = glm::vec2(start_to_end_normalized.y, -start_to_end_normalized.x);
glm::vec2 a = start + start_to_a_dir * half_thickness;
glm::vec2 b = start + start_to_b_dir * half_thickness;
glm::vec2 c = a + start_to_end_normalized * stem_length;
glm::vec2 d = b + start_to_end_normalized * stem_length;
/*
*
* (aln)-- |
* ---- |
* ---- |
* (e2s)----------s-------------e
* ---- |
* ---- |
* (bln)-- |
*
* ------len 1-----
*/
glm::vec2 a_line = end_to_start_normalized + start_to_a_dir;
glm::vec2 b_line = end_to_start_normalized + start_to_b_dir;
/*
* |o
* | o hyp = \sqrt{2} x
* x o
* | o
* |------x------- o
*/
a_line = glm::normalize(a_line) * (float) sqrt(2) * tip_length;
b_line = glm::normalize(b_line) * (float) sqrt(2) * tip_length;
glm::vec2 g = end + a_line;
glm::vec2 f = end + b_line;
const int num_flattened_vertices_in_arrow = 3 * 7;
float arrow[num_flattened_vertices_in_arrow] = {
a.x, a.y, 0.0f,
b.x, b.y, 0.0f,
c.x, c.y, 0.0f,
d.x, d.y, 0.0f,
end.x, end.y, 0.0f,
f.x, f.y, 0.0f,
g.x, g.y, 0.0f
};
for (int i = 0; i < num_flattened_vertices_in_arrow; i++) {
out_flattened_vertices[i] = arrow[i];
}
}
将其存储在顶点缓冲区后,我使用
glDrawElements
的索引顺序调用
{0, 1, 2}, {2, 1, 3}, {4, 5, 6}
来绘制它