# problem de-rotating a model

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);
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;
}
``````

Why are you using a mixture of legacy OpenGL matrix operations and your own matrix code?

The coordinates passed to glRasterPos() are transformed by the model-view and projection matrices in the same manner as for glVertex(), so if you want to position bitmaps relative to a vertex, you can just pass the vertex’ position to glRasterPos() while using the same matrices. You can apply a screen-space offset to the transformed position by using glBitmap() to render an empty bitmap with appropriate values for the xmove and ymove parameters.

Alternatively, you can perform all of the matrix arithmetic yourself and just pass the final matrices to OpenGL using glLoadMatrix() or glMultMatrix().

My problem is that I don’t know the location of the rotated and spun vertex.
Commenting out the transform command and placing the grid location into the printtext command utilizes the same transformations that rotated the vertices. However, passing the 2D printtext command into the resulting transformation matrix does not account for the depth (Z coordinate) being rotated. The result is that labels for all vertices sharing the same X and Y coordinates are overlaid.

``````//    transform(g[i], t);
sprintf(label, "%d", i);
//    printtext((int)(t[0]), (int)(t[1] ), label);
printtext((int)(g[i][0]), (int)(g[i][1] ), label);
``````

Using glMultMatrix() instead of my own code does make sense.

[QUOTE=GClements;1286977]Why are you using a mixture of legacy OpenGL matrix operations and your own matrix code?

The coordinates passed to glRasterPos() are transformed by the model-view and projection matrices in the same manner as for glVertex(), so if you want to position bitmaps relative to a vertex, you can just pass the vertex’ position to glRasterPos() while using the same matrices. You can apply a screen-space offset to the transformed position by using glBitmap() to render an empty bitmap with appropriate values for the xmove and ymove parameters.

Alternatively, you can perform all of the matrix arithmetic yourself and just pass the final matrices to OpenGL using glLoadMatrix() or glMultMatrix().[/QUOTE]

I have tried to implement your suggestion, unsuccessfully.
The matrix multiplication algorithm that I presented works. I have verified that using Octave. Even accounting for the fact that OpenGL uses column-major matrices instead of row-major matrices, I cannot get the same results using glMultMatrixf(matrix) as with my matrix multiplication subroutine. Partially, that is to be expected, since my answers do not result in placing the labels where they belong. However, neither does using glMultMatrixf…

This should be a math problem. Given that my matrix multiplication subroutine works, why are the labels incorrectly placed? After jumping that hurdle, I should be able to re-write the code using glMultMatrixf

[QUOTE=GClements;1286977]Why are you using a mixture of legacy OpenGL matrix operations and your own matrix code?

The coordinates passed to glRasterPos() are transformed by the model-view and projection matrices in the same manner as for glVertex(), so if you want to position bitmaps relative to a vertex, you can just pass the vertex’ position to glRasterPos() while using the same matrices. You can apply a screen-space offset to the transformed position by using glBitmap() to render an empty bitmap with appropriate values for the xmove and ymove parameters.

Alternatively, you can perform all of the matrix arithmetic yourself and just pass the final matrices to OpenGL using glLoadMatrix() or glMultMatrix().[/QUOTE]

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.
This is easier than you might think. You don’t have to calculate the transformed vertex coordinates to place the labels. OpenGL does it for you, if you use it correctly. This is what GLClements is saying. The code below is a simplified version your code. The transformations that rotate the vertices (i.e. glVertex commands), also rotate the glRaster commands which place the labels. Your ‘Transform’, ‘Printtext’, and ‘mult4matrix’ routines are not needed. A screen grab is also shown. Note that a space is printed to the screen before each label to move the label away from the vertex point a little.

[ATTACH=CONFIG]1466[/ATTACH]

``````// -------------------------------------------------------------------------------------------------
// --------------------------------   May 17, 2017.  Carmine.   ------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <GLUT/glut.h>
#include "glutstr.hpp"

float roll0 = 0.0, pitch0 = 0.0, roll = 0.0, pitch = 0.0, zoom = 1.0;
int xdown, ydown, WindowWidth = 720, WindowHeight = 540, mainWindow;

//------------------------------------------   init   ----------------------------------------------

void init (void)
{
roll = pitch = 0.0; zoom = 1.0;
glMatrixMode(GL_MODELVIEW);
}

//-----------------------------------------   display   --------------------------------------------

void display (void)
{
int i;
char label[2];
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}};

// Set up viewing transformations.

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
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);

// Draw cube vertices.

glPointSize (2.5);
glColor3f (0.0, 1.0, 1.0);
glBegin (GL_POINTS); for (i=0; i<8; i++) glVertex3fv(g[i]); glEnd();

// Label cube vertices.

for (i=0; i<8; i++)  {
glRasterPos3fv (g[i]);
sprintf (label, "%d", i);
glutBitmapCharacter (GLUT_BITMAP_9_BY_15, ' ');
glutBitmapCharacter (GLUT_BITMAP_9_BY_15, label[0]);
}

// Draw cube edges.

glColor3f (0.0, 0.0, 1.0);
glBegin (GL_LINE_LOOP); for (i=0; i<4; i++) glVertex3fv(g[i]); glEnd();
glBegin (GL_LINE_LOOP); for (i=4; i<8; i++) glVertex3fv(g[i]); glEnd();
glBegin (GL_LINES);     for (i=0; i<4; i++) {
glVertex3fv(g[i]); glVertex3fv(g[i+4]);
}  glEnd();

glutSwapBuffers ();
}

//------------------------------------------   move   ----------------------------------------------

void move (int x, int y)
{
roll  =  roll0 + 90 * (xdown -x) / WindowWidth;
pitch = pitch0 + 90 * (ydown -y) / WindowHeight;

display ();
}

//------------------------------------------   mouse   ---------------------------------------------

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;
}  else if (btn == 4) {
zoom /= 1.1;
}  else if (state = GLUT_UP) {
if (gup == 1) return;
roll0  += pitch;
pitch0 += roll;
}

gup = 1;
}

//------------------------------------------   main   ----------------------------------------------

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(700, 400);
mainWindow = glutCreateWindow("Print Labels");
init();
glutDisplayFunc (display);
glutMouseFunc   ( mouse );
glutMotionFunc  ( move)  ;
glutMainLoop();
return 0;
}

``````

Thank you.
Thankyouthankyouthankyou!

Reposting my solution with a few further mods.
This is a simplification of your code which does what GClements suggested.
Let OpenGL transform the labels for you.
You don’t need to do your own matrix multiplications.

[ATTACH=CONFIG]153[/ATTACH]

``````// -------------------------------------------------------------------------------------------------
// --------------------------------   May 17, 2017.  Carmine.   ------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <GLUT/glut.h>
#include "glutstr.hpp"

int   xdown, ydown, WindowWidth = 720, WindowHeight = 540;
float roll0 = 0.0, pitch0 = 0.0, roll = 0.0, pitch = 0.0, zoom = 1.0;

//------------------------------------------   moove   ---------------------------------------------

void moove (int x, int y)
{
roll  =  roll0 + 90 * (xdown-x) / WindowWidth;
pitch = pitch0 + 90 * (ydown-y) / WindowHeight;

glutPostRedisplay ();       // This should be used instead of 'display'.
}

//------------------------------------------   mouse   ---------------------------------------------

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;
}  else if (btn == 4) {
zoom /= 1.1;
}  else if (state = GLUT_UP) {
if (gup == 1) return;
roll0  += pitch;
pitch0 += roll;
}

gup = 1;
}

//-----------------------------------------   display   --------------------------------------------

void display (void)
{
int i;
char label[2];
static int g[8][3] = {{-10,-10,-10}, {10,-10,-10}, {10,10,-10}, {-10,10,-10},
{-10,-10, 10}, {10,-10, 10}, {10,10, 10}, {-10,10, 10}};

// Set up viewing transformations.

glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
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);

// Draw cube vertices.

glColor3f (0.0, 1.0, 1.0);
glBegin (GL_POINTS); for (i=0; i<8; i++) glVertex3iv(g[i]); glEnd();

// Label cube vertices.

for (i=0; i<8; i++)  {
glRasterPos3iv (g[i]);
sprintf (label, "%d", i);
glutBitmapCharacter (GLUT_BITMAP_9_BY_15, ' ');
glutBitmapCharacter (GLUT_BITMAP_9_BY_15, label[0]);
}

// Draw cube edges.

glColor3f (0.0, 0.0, 1.0);
glBegin (GL_LINE_LOOP); for (i=0; i<4; i++)  glVertex3iv(g[i]); glEnd();
glBegin (GL_LINE_LOOP); for (i=4; i<8; i++)  glVertex3iv(g[i]); glEnd();
glBegin (GL_LINES);     for (i=0; i<4; i++) {glVertex3iv(g[i]); glVertex3iv(g[i+4]);}
glEnd();

glutSwapBuffers ();
}

//-----------------------------------------   Init_GL   --------------------------------------------

void Init_GL (void)
{
glMatrixMode (GL_PROJECTION);
glMatrixMode (GL_MODELVIEW);

glEnable (GL_DEPTH_TEST);
glPointSize (6.5);
}

//----------------------------------------   Init_Glut   -------------------------------------------

void Init_Glut (void)
{
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize  (WindowWidth, WindowHeight);
glutInitWindowPosition (700, 400);
glutCreateWindow ("Print Labels");
glutMotionFunc   ( moove );
glutMouseFunc    ( mouse );
glutDisplayFunc  (display);
}

//------------------------------------------   main   ----------------------------------------------

int main (int argc, char* argv[])
{
glutInit (&argc,argv);
Init_Glut ();
Init_GL   ();
glutMainLoop();
return 0;
}

``````

[QUOTE=wmelgaard;1287011]Thank you.
Thankyouthankyouthankyou![/QUOTE]

(You’re welcome) x 4