The following program writes an 8 line cube, allows a mouse drag to rotate it, and then attempts to label the corners in their rotated location.
However, the more the model is rotated, the farther away from the vertices the labels are placed.
??
// labels.c
// This program writes a cube, which can be spun with a mouse drag, and then labels the corners.
// compile as gcc labels.c -lm -lglut -lGLEW -lGL
#include <stdio.h>
#include<math.h>
#include<time.h>
#include <GL/glew.h>
#include <GL/glext.h>
#include <GL/glut.h>
float roll0 = 0.0, pitch0 = 0.0, roll = 0.0, pitch = 0.0, zoom = 1.0;
int xdown, ydown, WindowWidth = 720, WindowHeight = 540, mainWindow;
void init(){
roll = pitch = 0.0; zoom = 1.0;
glMatrixMode(GL_MODELVIEW);
}
// multiply 4X4 matrix A by matrix B; answer is copied into matrix A
void mult4matrix(float A[4][4], float B[4][4]){
int i, j, k;
float C[4][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};
for(i=0; i<4; i++) for(j=0; j<4; j++) for(k=0; k<4; k++){
C[i][j] += A[i][k] *B[k][j];
}
for(i=0; i<4; i++) for(j=0; j<4; j++) A[i][j] = C[i][j];
}
void transform(float *in, float *t){
// build(?) a transformation matrix, multiply in[] by that matrix, put answers in in[]
// roll is rotation about X axis; pitch = rotation about Y axis
const double PI = 3.14159265358979323846;
float ix, iy, iz, rad, ox, oy, oz;
int i, j;
double iroll, ipitch, ialpha, igamma, oroll, opitch;
static float lroll=NAN, lpitch, lzoom=1.0, xmatrix[4][4]; // values from previous
const float imatrix[4][4] = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}; //identity
float mmatrix[4][4], vout[3] = {0, 0, 0};
if((lroll != roll) || (lpitch != pitch) || (lzoom != zoom)){
// compute transformation matrix based on updated values
lroll = roll; lpitch = pitch; lzoom = zoom;
// roll & pitch are in degrees; iroll & ipitch are in radians
iroll = roll *PI/180.0;
ipitch = pitch *PI/180.0;
// set xmatrix, mmatrix = identity matrix
for(i=0; i<4; i++) for(j=0; j<4; j++) xmatrix[i][j] = mmatrix[i][j] = imatrix[i][j];
xmatrix[0][0] = cos(iroll);
xmatrix[0][2] = sin(iroll);
xmatrix[2][0] = -sin(iroll);
xmatrix[2][2] = cos(iroll);
mmatrix[1][1] = cos(ipitch);
mmatrix[1][2] = -sin(ipitch);
mmatrix[2][1] = sin(ipitch);
mmatrix[2][2] = cos(ipitch);
mult4matrix(xmatrix, mmatrix);
for(i=0; i<4; i++) for(j=0; j<4; j++) mmatrix[i][j] = imatrix[i][j]; lzoom = 1.0;
mmatrix[0][0] = lzoom;
mmatrix[1][1] = lzoom;
mmatrix[2][2] = lzoom;
mult4matrix(xmatrix, mmatrix);
}
for(i=0; i<4; i++) for(j=0; j<4; j++)vout[i] += xmatrix[i][j] *in[j];
t[0] = vout[0]; t[1] = vout[1]; t[2] = vout[2]; t[3] = 0;
}
void printtext(int x, int y, char String[]) // labels etc for model
{
int i, stringsize;
//(x,y) is from the bottom left of the window
glPushMatrix();
glPushAttrib(GL_DEPTH_TEST);
glDisable(GL_DEPTH_TEST);
glRasterPos2i(x,y);
for(i=0; String[i] != 0 && i<10; i++){
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, String[i]);
}
glPopAttrib();
glPopMatrix();
}
void display(){
float g[8][3] = {{-10.0, -10.0, -10.0},{10.0, -10.0, -10.0}, {10.0, 10.0, -10.0}, {-10.0, 10.0, -10.0},
{-10.0, -10.0, 10.0},{10.0, -10.0, 10.0}, {10.0, 10.0, 10.0}, {-10.0, 10.0, 10.0}};
float t[3];
int i;
char label[10];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glLoadIdentity();
glOrtho(-20.0, 20.0, -20.0, 20.0, -20.0, 20.0);
glScalef(zoom, zoom, zoom);
glRotatef(roll, 0.0, 1.0, 0.0);
glRotatef(pitch, 1.0, 0.0, 0.0);
glPointSize(2.5);
glColor3f(0.0, 1.0, 1.0);
glBegin(GL_POINTS);
for(i=0; i<8; i++) glVertex3fv(g[i]);
glEnd();
// print grid identification numbers to screen
glColor3f(0.0, 0.3, 1.0);
for(i=0; i<8; i++){
transform(g[i], t);
sprintf(label, "%d", i);
printtext((int)(t[0]), (int)(t[1] ), label);
// offset the labels from the grid points
// printtext((int)(t[0]+2), (int)(t[1] +2), label);
}
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_LINE_STRIP);
for(i=0; i<4; i++) glVertex3fv(g[i]);
glVertex3fv(g[0]);
for(i=4; i<8; i++) glVertex3fv(g[i]);
glVertex3fv(g[4]);
glEnd();
glBegin(GL_LINES);
for(i=1; i<4; i++){
glVertex3fv(g[i]);
glVertex3fv(g[i+4]);
}
glEnd();
glutSwapBuffers();
}
void move(int x, int y){
roll = roll0 + 90*(xdown -x)/WindowWidth;
pitch = pitch0 + 90*(ydown -y)/WindowHeight;
display();
}
void mouse(int btn, int state, int x, int y){
static int gup = 1;
if(btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN){
xdown = x;
ydown = y;
gup = 0;
return;
}
else if(btn == 3){ // mouse wheel
zoom *= 1.1;
display();
}
else if(btn == 4){
zoom /= 1.1;
display();
}
else if (state = GLUT_UP){
if(gup == 1)return;
roll0 += pitch;
pitch0 += roll;
}
gup = 1;
display();
}
int main(int argc, char* argv[]){
int WindowWidth = 720, WindowHeigyt=540;
glutInit(&argc,argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(WindowWidth, WindowHeight);
glutInitWindowPosition(100, 100);
mainWindow = glutCreateWindow("Print Labels");
init();
glutDisplayFunc(display);
glutMouseFunc (mouse);
glutMotionFunc(move);
glutMainLoop();
return 0;
}