当我破解我的平截头体插图程序时,我写了一个小箭头绘图辅助函数draw_arrow
,它绘制了一个屏幕对齐的箭头 + 注释(使用 glutStorkeCharacter)。
请注意,它使用固定函数管道模型视图矩阵来确定局部空间基向量。如果要在基于着色器的管道中使用它,则必须通过附加参数将模型视图矩阵传递给它。
https://github.com/datenwolf/codesamples/blob/master/samples/OpenGL/frustum/frustum.c
void draw_arrow(
float ax, float ay, float az, /* starting point in local space */
float bx, float by, float bz, /* starting point in local space */
float ah, float bh, /* arrow head size start and end */
char const * const annotation, /* annotation string */
float annot_size /* annotation string height (local units) */ )
{
int i;
GLdouble mv[16];
glGetDoublev(GL_MODELVIEW_MATRIX, mv);
/* We're assuming the modelview RS part is (isotropically scaled)
* orthonormal, so the inverse is the transpose.
* The local view direction vector is the 3rd column of the matrix;
* assuming the view direction to be the normal on the arrows tangent
* space taking the cross product of this with the arrow direction
* yields the binormal to be used as the orthonormal base to the
* arrow direction to be used for drawing the arrowheads */
double d[3] = {
bx - ax,
by - ay,
bz - az
};
normalize_v(d);
double r[3] = { mv[0], mv[4], mv[8] };
int rev = scalarproduct_v(d, r) < 0.;
double n[3] = { mv[2], mv[6], mv[10] };
{
double const s = scalarproduct_v(d,n);
for(int i = 0; i < 3; i++)
n[i] -= d[i]*s;
}
normalize_v(n);
double b[3];
crossproduct_v(n, d, b);
/* Make a 60° arrowhead ( sin(60°) = 0.866... ) */
GLfloat const pos[][3] = {
{ax, ay, az},
{bx, by, bz},
{ ax + (0.866*d[0] + 0.5*b[0])*ah,
ay + (0.866*d[1] + 0.5*b[1])*ah,
az + (0.866*d[2] + 0.5*b[2])*ah },
{ ax + (0.866*d[0] - 0.5*b[0])*ah,
ay + (0.866*d[1] - 0.5*b[1])*ah,
az + (0.866*d[2] - 0.5*b[2])*ah },
{ bx + (-0.866*d[0] + 0.5*b[0])*bh,
by + (-0.866*d[1] + 0.5*b[1])*bh,
bz + (-0.866*d[2] + 0.5*b[2])*bh },
{ bx + (-0.866*d[0] - 0.5*b[0])*bh,
by + (-0.866*d[1] - 0.5*b[1])*bh,
bz + (-0.866*d[2] - 0.5*b[2])*bh }
};
GLushort const idx[][2] = {
{0, 1},
{0, 2}, {0, 3},
{1, 4}, {1, 5}
};
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, pos);
glDrawElements(GL_LINES, 2*5, GL_UNSIGNED_SHORT, idx);
glDisableClientState(GL_VERTEX_ARRAY);
if(annotation) {
float w = 0;
for(char const *c = annotation; *c; c++)
w += glutStrokeWidth(GLUT_STROKE_ROMAN, *c);
w *= annot_size / 100.;
float tx = (ax + bx)/2.;
float ty = (ay + by)/2.;
float tz = (az + bz)/2.;
GLdouble r[16] = {
d[0], d[1], d[2], 0,
b[0], b[1], b[2], 0,
n[0], n[1], n[2], 0,
0, 0, 0, 1
};
glPushMatrix();
glTranslatef(tx, ty, tz);
glMultMatrixd(r);
if(rev)
glScalef(-1, -1, 1);
glTranslatef(-w/2., annot_size*0.1, 0);
draw_strokestring(GLUT_STROKE_ROMAN, annot_size, annotation);
glPopMatrix();
}
}
帮助自己。