PDA

View Full Version : Adding text



Sniipe
01-16-2006, 05:20 AM
Hello, I hope you guys can help me with this;
The application I am doing you will be able to right click; menu pops up and you can choose add text. Once selected you can type text.

I have the menu working but am stuck with the adding text. It will add alright but not in the correct position (0,0) as opposed to where the mouse is.

so, so far I have this:


if(id==8) //Add text
{
printf("About to add text\n");
glutKeyboardFunc(keyboard);
glFlush();
} That (id==8) is the menu item.
keyboard function is as follows


void keyboard(unsigned char key, int x, int y)
{
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, key);
glFlush();
}So by doing that the text prints out properly but only at position (0,0). I hope someone can help me out. I've been stuck a good while now. Thanks.

songho
01-16-2006, 06:06 AM
I think you missed;
glRasterPos2i(x, y);

Sniipe
01-16-2006, 06:28 AM
hello Song,
thanks for the quick reply; I gather that I missed glRasterPos2i(x, y);
That would have to be called before it goes into the keyboard function, but I can't get the current mouse position. The menu pops open at the right click but there is no way to get those x,y co-ordinates... well there probably is a way but I'm stumped.

Sniipe
01-16-2006, 06:38 AM
If it helps I'll outline what my simple program does:

in - int main(int argc, char** argv)
I set up window and call addmenu();

in - void addmenu()
I set up menu and sub menu's then add a menu id
menu_id = glutCreateMenu(myRightClickMenu);
then
glutAttachMenu(GLUT_RIGHT_BUTTON);

in - void myRightClickMenu(int id)
on "add text" I call, glutKeyboardFunc(keyboard);

then finally:


void keyboard(unsigned char key, int x, int y)
{
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, key);
glFlush();
}

Sniipe
01-16-2006, 07:54 AM
I'm stuck again but I found the answer with the glut function for getting the position

before the keyboard function is called I set the raster points by calling: glutPassiveMotionFunc(passive);

in that function I get the real x and real y position by doing the following:



void passive(int x, int y) //find the current position of the mouse
{
GLint viewport[4];
GLdouble mvmatrix[16], projmatrix[16];
GLint realy; /* OpenGL y coordinate position */

glGetIntegerv (GL_VIEWPORT, viewport);
glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);
realy = viewport[3] - (GLint) y - 1;
glRasterPos2f(x, realy);
}

songho
01-16-2006, 08:19 AM
Sniipe,
Your keyboard callback function has already got current cursor position.
void keyboard(unsigned char key, int x, int y)

Once a key is pressed, glut sends the current (x,y) coords of the cursor to your function.

I believe you also have mouse button callback function, glutMouseFunc().

Your callback might look like this;
void mouse(int button, int state, int x, int y);

It is more sense to me to get the current cursor position when mouse button is clicked.
==song==

Sniipe
01-16-2006, 09:41 AM
Song, thanks again for your quick reply. Here is my code so far. if I have glRasterPos2i(x, y) in the keyboard function the characters will print out on top of each other. I need to get the position before that hence the passive function. If I use the mouse function it will miss the first character I print.



#include <GL/glut.h>
#include <stdio.h>

/* globals */
GLsizei wh = 500, ww = 500; /* initial window size */
GLfloat size = 3.0; /* half side length of square */
static int submenu_shape;
static int submenu_fill;
static int menu_id;

void keyboard(unsigned char key, int x, int y)
{
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, key);
glFlush();
}

void passive(int x, int y) //find the current position of the mouse
{
GLint viewport[4];
GLdouble mvmatrix[16], projmatrix[16];
GLint realy; /* OpenGL y coordinate position */

glGetIntegerv (GL_VIEWPORT, viewport);
glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);
realy = viewport[3] - (GLint) y - 1;
glRasterPos2f(x, realy);
}

/* Right mouse button click - its menu system*/
void myRightClickMenu(int id)
{
//Right click menu options
if(id==0) //Exit has been clicked
{
exit(0);
}
if(id==1) //clear screen has been clicked
{
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
}
if(id==2) //shape->square
{
//not working yet
}
if(id==3) //shape->circle
{
//not working yet
}
if(id==4) //shape->triangle
{
//not working yet
}
if(id==5) //shape->bezier curve
{
//not working yet
}
if(id==6) //Fill->On
{
//not working yet
}
if(id==7) //Fill->Off
{
//not working yet
}
if(id==8) //Add text; with this -> where ever your mouse is is where u start typing.
{
glutPassiveMotionFunc(passive);
glutKeyboardFunc(keyboard);
}

}


/* reshaping routine called whenever window is resized or moved */
void myReshape(GLsizei w, GLsizei h)
{
/* adjust clipping box */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, (GLdouble)w, 0.0, (GLdouble)h, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

/* adjust viewport and clear */
glViewport(0,0,w,h);
glClear(GL_COLOR_BUFFER_BIT);
glFlush();

/* set global size for use by drawing routine */
ww = w;
wh = h;
}
/* myinit function */
void myinit()
{

glClearColor (0.0, 0.0, 0.0, 1.0);
glViewport(0,0,ww,wh);
/* Pick 2D clipping window to match
size of screen window. This choice avoids having to scale object
coordinates each time window is resized. */

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, (GLdouble) ww , 0.0, (GLdouble) wh , -1.0, 1.0);

/* set clear color to black and clear window */
glClearColor (0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
}

/* display callback required by GLUT */
void display()
{}

/* Add menu function called from Main*/
void addmenu()
{
submenu_shape = glutCreateMenu(menu_id);
glutAddMenuEntry("Square",2);
glutAddMenuEntry("Circle",3);
glutAddMenuEntry("Triangle",4);
glutAddMenuEntry("Bezier Curve",5);

submenu_fill = glutCreateMenu(menu_id);
glutAddMenuEntry("On",6);
glutAddMenuEntry("Off",7);

menu_id = glutCreateMenu(myRightClickMenu);

glutAddMenuEntry("Clear Screen", 1);
glutAddSubMenu("Shape",submenu_shape);
glutAddSubMenu("Fill",submenu_fill);
glutAddMenuEntry("Add Text",8);
glutAddMenuEntry("Exit", 0);

//menu attached to right mouse button
glutAttachMenu(GLUT_RIGHT_BUTTON);
}

/* Main */


int main(int argc, char** argv)
{
glutInit(&amp;argc,argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutCreateWindow("Assignment 1: Rory Carroll - D04102698");
myinit ();
glutReshapeFunc (myReshape);
glutDisplayFunc(display);
addmenu(); /* call function to add menu to right mouse button */
glutMainLoop();
}

songho
01-16-2006, 01:37 PM
Sniipe,
I ran your application and understood what you meant.

I suggest 2 things;
- Call glRasterPos*() only once when first key entered.
- Get the cursor coords from keyboard callback.

In order to do that, you may need flag variables in global scope. The code snippet looks like this;


// global vars
bool addTextSelected = false;
bool needCursorPos = true;
...

void myRightClickMenu(int id)
{
// init flags
addTextSelected = false;

...
if(id==8) //<-- better with SWITCH statement instead of IF
{
addTextSelected = true;
needCursorPos = true;
}
}
...

// keyboard CALLBACK
void keyboard(unsigned char key, int x, int y)
{
if(addTextSelected)
{
// set raster position when the first key entered
if(needCursorPos)
{
glRasterPos2i(x,wh-y); // invert vertical direction
needCursorPos = false;
}

// write text
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, key);
glFlush();
}
}Notice that glutKeyboardFunc() is removed from myRightClickMenu(), since registering a callback function is required only once.

I noticed clearing screen problem due to drawing a character one at a time. Other option might be storing text into a buffer. So you can clear screen and rewrite a string in the buffer every frame.
==song==

Sniipe
01-23-2006, 07:04 AM
Tried to add your code but ran into difficulty:

c:\Documents and Settings\Rory Carroll\My Documents\Graphics\Assignment1\rorycarroll.c(10) : error C2061: syntax error : identifier 'addTextSelected'
c:\Documents and Settings\Rory Carroll\My Documents\Graphics\Assignment1\rorycarroll.c(10) : error C2059: syntax error : ';'
c:\Documents and Settings\Rory Carroll\My Documents\Graphics\Assignment1\rorycarroll.c(10) : error C2513: '/*global*/ ' : no variable declared before '='
c:\Documents and Settings\Rory Carroll\My Documents\Graphics\Assignment1\rorycarroll.c(10) : error C2065: 'false' : undeclared identifier
c:\Documents and Settings\Rory Carroll\My Documents\Graphics\Assignment1\rorycarroll.c(11) : error C2061: syntax error : identifier 'needCursorPos'
c:\Documents and Settings\Rory Carroll\My Documents\Graphics\Assignment1\rorycarroll.c(11) : error C2059: syntax error : ';'
c:\Documents and Settings\Rory Carroll\My Documents\Graphics\Assignment1\rorycarroll.c(11) : error C2513: '/*global*/ ' : no variable declared before '='
c:\Documents and Settings\Rory Carroll\My Documents\Graphics\Assignment1\rorycarroll.c(11) : error C2065: 'true' : undeclared identifier

I reckon I haven't included the right file for it. All I have is:
#include <GL/glut.h>
#include <stdio.h>

Sniipe
01-23-2006, 07:18 AM
I got it to work when I used int's instead and when I eventually remembered to glutKeyboardFunc(keyboard). Thanks SongHo, ur a legend!

songho
01-23-2006, 07:27 AM
I guess you are using C compiler.
"bool" is a C++ specific data type, so change "bool" to "int", "true" to 1 and "false" to "0".

Sniipe
01-23-2006, 07:30 AM
hmm, using visual studio... Surely that has everything... no worries I'm happy that I got it working. cheers again.