I'm trying to display a text-overlay (basically a help screen which shows my keyboard shortcuts) on top of a 3D Texture I'm rendering. The texture works great and I've got some east-to-use rotations and translations for the user.
My thought was to use
const unsigned char tmp[100] = "text to render";
glRasterPos2i(x, y);
glColor4b(255, 255, 255, 255);
glutBitmapString(GLUT_BITMAP_HELVETICA_18, tmp);
As recommended in How do I use glutBitmapString() in C++ to draw text to the screen? .
This works great except that the text now rotates with the object instead of remaining in a static location on the screen. I read some documentation and found that the glRasterPos functions are manipulated when you manipulate the model view matrix:
The object coordinates presented by glRasterPos are treated just like those of a glVertex command: They are transformed by the current modelview and projection matrices and passed to the clipping stage.
-Source
I then found via another post that you could push and pop the current matrix with glPushMatrix and glPopMatrix.
-Source
When I do this, the text disappears all together. At first I thought I might have had the coordinates wrong for the text, but I tried x=y=0 through x=y=25 in intervals of .01 and never saw the text. It's still possible I'm misunderstanding where this should be drawn, but I'm not sure what to try next.
My drawing function is calling something akin to:
glLoadIdentity();
glPushMatrix();
glTranslatef(0,0,-sdepth);
glRotatef(-stheta, 1.0, 0.0, 0.0);
glRotatef(sphi, 0.0, 0.0, 1.0);
glRotatef(rotateX,0,1,1);
glRotatef(rotateY,1,0,0);
glTranslatef(-0.5,-0.5,-0.5);
glPopMatrix();
glRasterPos2i(2, 2);
glColor4b(255, 255, 255, 255);
glutBitmapString(GLUT_BITMAP_HELVETICA_18, tmp);
Anyone have any recommendations for debug/troubleshooting steps to try to get this text to display in a single, static location on the screen?
Well, if glRasterPos is treated the same way as glVertex, then you need to set up proper projection (GL_PROJECTION) matrix (using gluOrtho2D) before calling glRasterPos.
Give this a shot:
#include <GL/glut.h>
#include <string>
using namespace std;
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3ub(255,0,0);
glPushMatrix();
glScalef(5,5,5);
glBegin(GL_QUADS);
glVertex2f(-1,-1);
glVertex2f(1,-1);
glVertex2f(1,1);
glVertex2f(-1,1);
glEnd();
glPopMatrix();
glColor3ub(0,255,0); // A
glRasterPos2i(0,0); // B
string tmp( "wha-hey!" );
for( size_t i = 0; i < tmp.size(); ++i )
{
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, tmp[i]);
}
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double aspect_ratio = (double)w / (double)h;
glOrtho(-10*aspect_ratio, 10*aspect_ratio, -10, 10, -1, 1);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(800,600);
glutCreateWindow("Text");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return EXIT_SUCCESS;
}
Oddly enough swapping lines A and B causes the glColor3ub() call to not take effect. I think that's what you were running into with the code sequence you posted.
As an aside glColor4b() takes chars which max out at 127. You should switch to glColor4ub() if you want to persist in passing in 255.
Documented here ("The sequence of glRasterPos(), glColor(), glBitmap() doesn't result in the desired bitmap color"), but no explanation given :(
EDIT: Ah ha! The current raster position contains its own color state, which is only updated during a glRasterPos() call.
Related
I'm trying to use GLUT for a specific openGL project. I've put glut32.dll/glut.h/glut32.lib in their required directories. After adding a source file to the project in Visual Studio, when I hit debug/run, it doesn't show any error what so ever. The source code I'm using is that of a colored cube that rotates. Now after hitting debug, the output console does show up with the colored cube, but only for a split second, which was not supposed to happen.
the code I'm using:
#include <GL/glut.h>
#define window_width 640
#define window_height 480
// Main loop
void main_loop_function() {
// Z angle
static float angle;
// Clear color (screen)
// And depth (used internally to block obstructed objects)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Load identity matrix
glLoadIdentity();
// Multiply in translation matrix
glTranslatef(0, 0, -10);
// Multiply in rotation matrix
glRotatef(angle, 0, 0, 1);
// Render colored quad
glBegin(GL_QUADS);
glColor3ub(255, 000, 000);
glVertex2f(-1, 1);
glColor3ub(000, 255, 000);
glVertex2f(1, 1);
glColor3ub(000, 000, 255);
glVertex2f(1, -1);
glColor3ub(255, 255, 000);
glVertex2f(-1, -1);
glEnd();
// Swap buffers (color buffers, makes previous render visible)
glutSwapBuffers();
// Increase angle to rotate
angle += 0.25;
}
// Initialze OpenGL perspective matrix
void GL_Setup(int width, int height) {
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glEnable(GL_DEPTH_TEST);
gluPerspective(45, (float) width / height, .1, 100);
glMatrixMode(GL_MODELVIEW);
}
// Initialize GLUT and start main loop
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitWindowSize(window_width, window_height);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("GLUT Example!!!");
glutIdleFunc(main_loop_function);
GL_Setup(window_width, window_height);
glutMainLoop();
}
Can someone tell me what might be causing this? The code doesn't have any error. And since the output is indeed showing for only half of a second, I'm assuming the GLUT files have been placed correctly. Then what might be causing the console to go away within a second?
With glut you should not draw things from the function attached to glutIdleFunc but rather glutDisplayFunc.
Use glutDisplayFunc(main_loop_function); and create a new timer function doing the angle += 0.25; and connect the callback with glutTimerFunc(...) to rotate in a timed fashion rather than on every redraw, which may not happen in regular intervals.
I've been trying to draw a cone and a cylinder using GLUT. The code I've written so far takes two points from the user, which represents the height of the cone/cylinder, and I want to draw a cone and a cylinder using the two points.
I looked up Google and found standard functions called glutWireCone() and gluCylinder(), but I'm unable to understand how to use these functions to draw in the manner that I want to draw. Can someone tell me how to draw a cone and a cylinder using the two points? Please let me know if you need some extra information to understand my question correctly.
Here are my init() and main() functions for you to know the settings of my program:
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, WINDOW_WIDTH-1, WINDOW_HEIGHT-1, 0, -1000.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutInitWindowPosition(220, 80);
glutCreateWindow("Mini Paint - 3D");
init();
glutDisplayFunc(display);
glutMouseFunc(mouseClick);
glutMotionFunc(mouseMove);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
Well lets take that gluCylinder function and apply it to your display function. Look at it's parameters:
void gluCylinder(GLU quadric* quad,
GLdouble base,
GLdouble top,
GLdouble height,
GLint slices,
GLint stacks);
So you want to draw a cylinder given the height parameter as input. I'm guessing everything else will remain constant. every time you render you'll want to use glPushMatrix and maybe glRotatef depending on how you would like its orientation, ending this call with a glPopMatrix
Ex: OnRender(float pHeight)
void OnRender(float pHeight) {
glClearColor(1.0f, 0.0f, 0.0f, 1.0f); //clear
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity();
gluCylinder(quadratic, 0.1f, 0.1f, pHeight, 32, 32);
glFlush();
}
declaring a quadratic object:
GLUquadricObj *quadratic;
quadratic = gluNewQuadric();
gluCylinder documentation: https://www.opengl.org/sdk/docs/man2/xhtml/gluCylinder.xml
I am starting with openGL and c++, and I was wondering why I don't see anything on the window. Here is my code:
#include <GLUT/GLUT.h>
#include <stdlib.h>
void init() {
glClearColor(0, 0, 1, 0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, 1.0, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -10);
}
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glVertex3i(-0.5, -0.5, 0);
glVertex3i(0, 0.5, 0);
glVertex3i(0.5, -0.5, 0);
glEnd();
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE| GLUT_RGBA);
glutInitWindowPosition(200, 200);
glutInitWindowSize(400, 400);
glutCreateWindow("Window");
init();
glutDisplayFunc(display);
glutMainLoop();
}
I have a few questions:
If I run the program like this all I see is a white window... Didn't I set the color to blue?
When I do glutSwapBuffers() at the end of display function and run the program, I see the blue window without the triangle. So, I thought glutSwapBuffers() function only worked with double buffering.
And the most important, where the hell is my triangle? O.o Didn't I translate the camera with glTranslatf() function to -10 in the z-axes? If you are wondering why I used gluPerspective, I have to say that I am trying out new things, but neither works if I use gluOrtho2D().
I don't know if I am missing something or what. Maybe I need to search more information about this, but I think most of the code is correct.
1 & 2) Well you don't have to call glutSwapBuffers() when using single buffer. But you have to call glFlush(), so the draw commands are executed on the GPU.
3) I noticed that you are creating vertices with double coordinates, but you are calling integer version of glVertex** function (decimal part will be truncated) - it means that you will be drawing triangle with zero size.
Use glVertex3d() or glVertex3f() instead of glVertex3i().
Small note: intermediate mode is deprecated in the latest OpenGL.
I am making a simple GLUT program which tracks the mouse and put points on the path.
Well This is my code:
void init()
{
glClearColor( 0.0, 0.0, 1.0, 1.0);
glMatrixMode( GL_PROJECTION);
gluOrtho2D( 0.0, 400.0, 0.0, 400.0);
for(int i=0;i<5000;i++)
{
arr[i][0]=0;
arr[i][1]=0;
}
glPointSize(10.0);
}
void drawPoints()
{
glBegin( GL_POINTS );
glColor3f( 0.0,0.0,0.0 );
for ( int i = 0; i < z; i++ )
{
glVertex2f( arr[i][0], arr[i][1]);
}
glEnd();
}
void myDisplay()
{
glClear( GL_COLOR_BUFFER_BIT);
drawPoints();
glutSwapBuffers();
glutPostRedisplay();
}
void myMouseMove( int x, int y)
{
arr[z][0]=x;
arr[z++][1]=y;
}
int main( int argc, char ** argv)
{
glutInit( &argc, argv);
glutInitDisplayMode( GLUT_DOUBLE| GLUT_RGB);
glutInitWindowPosition( 100, 100);
glutInitWindowSize(600,600);
glutCreateWindow( "Testing");
init();
glutDisplayFunc( myDisplay);
glutPassiveMotionFunc( myMouseMove);
glutMainLoop();
return 0;
}
However I am having few problems:
Y coordinate runs in opposite direction.
Draws point ahead of cursor position(while moving in a direction).
Is there any better way to do this?
The Y coordinate being flipped is actually expected behavior. Simply correct for it in your code and you should be fine.
If you want to make sure that your rendered image and mouse cursor are completely synchronized, simply have glut hide the mouse cursor, and then render it yourself using OpenGL.
You should be aware that when using a traditional projection matrix in OpenGL: (0,0) is the lower-left corner. Most window systems will map (0,0) to the top-left corner.
In some circumstances, you can make them match up simply by swapping the bottom/top fields in your call to glOrtho (...) or gluOrtho2D (...) - this has other consequences like reversing polygon winding, so it is not always the best approach.
As for "drawing points ahead of the cursor," I think you may be describing input latency (particularly if you are using VSYNC).
When you use a software cursor vs. hardware cursor the position of the mouse may be off by one or more frames. There is a somewhat technical discussion here (see: Idiosyncrasies) on the effect of buffer swap intervals (OpenGL's mechanism for VSYNC) on input latency.
To fix the inversion do 600 - y for setting arr element. Also your gluOrtho2D is on a scale of 400 by 400 while your windows is 600 by 600 so change your gluOrtho2D scale to the same as the window size and you'll be fine.
I'm trying to load 3D models from .obj format and it draws the object on the scren without any problem but when I resize the screen everything disappear. Here's the code:
Obj* object = new Obj();
GLuint texture[1];
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0,(double)w / (double)h,1.0,200.0);
}
void initRendering() {
object->GetObj("cube.obj");
glShadeModel(GL_LINEAR);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glEnable(GL_DEPTH_TEST);
}
void handleKeypress(unsigned char key, int x, int y) {
switch (key) {
case 27:
{
exit(0);
break;
}
}
}
void drawScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glRotatef(45.0,0.0,1.0,0.0);
object->DrawObj();
glPopMatrix();
glutSwapBuffers();
glFlush();
}
int _tmain(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 400);
glutCreateWindow("3D");
initRendering();
glutReshapeFunc(handleResize);
glutDisplayFunc(drawScene);
glutKeyboardFunc(handleKeypress);
glutMainLoop();
return 0;
}
And here's the code for Obj.DrawObj():
glBegin(GL_TRIANGLES);
for(int i = 0;i < faces.capacity()-1;i++)
{
glVertex3f(vertices[faces[i].vertex1].cordinate1,vertices[faces[i].vertex1].cordinate2,vertices[faces[i].vertex1].cordinate3);
glVertex3f(vertices[faces[i].vertex2].cordinate1,vertices[faces[i].vertex2].cordinate2,vertices[faces[i].vertex2].cordinate3);
glVertex3f(vertices[faces[i].vertex3].cordinate1,vertices[faces[i].vertex3].cordinate2,vertices[faces[i].vertex3].cordinate3);
}
glEnd;
In your drawing code you set the projection matrix, which is good. However you set it to identity. In the resize handler you're setting the projection matrix as well, but you shouldn't do it there; yes I know the tutorials have it all there, but this is very bad style. You should move all the code currently in the reshape handler into the drawing handler, replacing the current setting of the projection matrix.
I can see that you're still confused by reading your PasteBin. Let me try to explain:
The reason why you can see your object the first time you draw it is because you have not set a projection matrix. So your object is drawn directly in normalized device coordinates (-1 to 1 range).
When you resize, you're setting the projection matrix for the first time, and this changes what viewing region is drawn to your screen. Your object as it is initially drawn is outside of the viewing region defined by your projection matrix (it is on top of the camera and I guess in front of the near plane. You have to move the object back away from the camera so that it is inside the view frustum. This is what datenwolf was suggesting.
However at the same time you introduced other errors into your code, particularly that you stopped resetting the projection matrix in handleResize. You have to always clear the projection matrix before you call gluPerspective, or else you will get a bogus result.
If you take the exact code from your pastebin, and add a glLoadIdentity to handleResize, I think that should work then:
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); //<--- add
glLoadIdentity(); //<--- add
gluPerspective(45.0,(double)w / (double)h,1.0,200.0);
}
Also, you're still clearing the projection matrix during the drawScene function. When you clear the matrix, you're throwing away the perspective setting that you just set in handleResize, you don't want to do that.
So basically:
Set the Projection matrix in handleResize and on initialization
Don't touch the projection matrix in drawScene
Translate the object so that it fits into the viewing frustum.