I'm writing a Level Editor and I'm using the GLUT to display text inside an opengl canvas. However, I would like to scale the text with the canvas instead of staying at the given size (18 at this moment).
How am I able to do this? A friend of mine suggested to create my own font but I think that's a bit much.
This is the code I'm using
public void showCharacters(GL gl, String text) {
final GLUT glut = new GLUT();
System.out.println(text);
if (text != null) {
gl.glColor3f(0.0f, 0.0f, 0.0f);
gl.glRasterPos2f(x + (sizeX / 10), (y - (sizeY)));
glut.glutBitmapString(GLUT.BITMAP_HELVETICA_18, text);
}
}
Use glutStroke*() and GLUT_STROKE_*:
#include <GL/glut.h>
#include <cstring>
int glWidth( void* font, const char* str )
{
int width = 0;
for( size_t i = 0; i < strlen( str ); ++i )
{
width += glutStrokeWidth( font, (int)str[i] );
}
return width;
}
void glPrint( void* font, const char* str )
{
for( size_t i = 0; i < strlen( str ); ++i )
{
glutStrokeCharacter( font, (int)str[i] );
}
}
void display()
{
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
double ar = w / h;
glOrtho( -250 * ar, 250 * ar, -250, 250, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
void* font = GLUT_STROKE_MONO_ROMAN;
const char* str = "Hello";
glTranslatef( -glWidth( font, str ) / 2.0f, 0, 0 );
glPrint( font, str );
glutSwapBuffers();
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "GLUT" );
glutDisplayFunc( display );
glutMainLoop();
return 0;
}
Related
I'm trying to do an animation which ball starts dropping with affects of gravity but unfortunately the ball is too slow. I actually found a way for it which is to change
double dt = (cur - last) / 1000.0;
to
double dt = (cur - last) / 100.0;
but that time, the bug is that position of the ball is kind of wrong because the ball starts dying :). If you work the animation you may understand what I'm trying to say!
The main code is there :
#include <GL/glut.h>
#include <vector>
#include <bits/stdc++.h>
using namespace std;
#include <glm/glm.hpp>
#include <glm/gtx/norm.hpp>
using namespace glm;
int seconds_past = 0;
struct Ball{
int radius;
dvec3 pos;
dvec3 vel;
double acc = -9.8;
bool last, made = false;
dvec3 last_vel;
void Integrate(double cur, double dt){
static int count = 0;
count++;
vel += dvec3{vel[0], acc * dt, 0};
pos = pos + vel * dt;
std::cout << vel[1] << " " << count << std::endl;
}
void HandleCollisions(){
if(pos[1] - 10 < -100){
std::cout << "true" << std::endl;
vel = -vel;
}
}
};
void Integrate( vector< Ball >& particles, double cur, double dt)
{
for( size_t i = 0; i < particles.size(); ++i )
{
particles[i].Integrate( cur, dt );
particles[i].HandleCollisions();
}
}
vector< Ball > particles;
void display()
{
// use last frame time to calculate delta-t
static int last = glutGet( GLUT_ELAPSED_TIME );
int cur = glutGet( GLUT_ELAPSED_TIME );
double dt = ( cur - last ) / 1000.0;
last = cur;
Integrate( particles, cur, dt);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
double ar = w / h;
glOrtho( -100 * ar, 100 * ar, -100, 100, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
// draw particles
glPointSize( 50 );
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 3, GL_DOUBLE, sizeof( Ball ), &particles[0].pos[0] );
glDrawArrays( GL_POINTS, 0, particles.size() );
glDisableClientState( GL_VERTEX_ARRAY );
glutSwapBuffers();
}
void timer( int value )
{
glutPostRedisplay();
glutTimerFunc( 1000.0/60.0, timer, value );
}
int main(int argc, char **argv)
{
particles.resize(1);
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 600, 600 );
glutCreateWindow( "GLUT" );
glutDisplayFunc( display );
glutTimerFunc( 0, timer, 0 );
glutMainLoop();
return 0;
}
I'm trying to just create a simple program that draws points where I click.
I declare a struct that holds the coordinates and the color of each point.
I declare a global vector< Point > that holds the list of points. The mouse input is well recorded and printed on the cout, but the points are not draw.
Any idea why I am missing in the initialization of GLUT?
#include <GL/freeglut_std.h>
#include <GL/gl.h>
#include <vector>
#include <iostream>
using namespace std;
struct Point
{
float x, y;
unsigned char r, g, b, a;
};
vector< Point > points;
void drawPoints()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-50, 50, -50, 50, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// draw
glColor3ub( 255, 255, 255 );
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_COLOR_ARRAY );
glVertexPointer( 2, GL_FLOAT, sizeof(Point), &points[0].x );
glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(Point), &points[0].r );
glPointSize( 3.0 );
glDrawArrays( GL_POINTS, 0, points.size() );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
glFlush();
glutSwapBuffers();
}
void OnMouseClick(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
{
//store the x,y value where the click happened
Point p = Point();
p.x = (float)x;
p.y = (float)y;
p.r = 255;
p.g = 255;
p.b = 255;
p.a = 255;
points.push_back(p);
for (vector<Point>::iterator it = points.begin(); it != points.end(); ++it)
{
cout << it->x << " " << it->y << " " << flush;
}
cout << endl;
glutPostRedisplay();
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("OpenGL - Drawing points");
glutDisplayFunc(drawPoints);
glutMouseFunc(OnMouseClick);
glutMainLoop();
return 0;
}
Coordinate system mismatch, either transform GLUT's mouse coordinates into your chosen glOrhto() coordinate system or change that call to match GLUT's mouse coordinate system.
Example of the second way:
#include <GL/glut.h>
#include <vector>
using namespace std;
struct Point
{
float x, y;
unsigned char r, g, b, a;
};
vector< Point > points;
void drawPoints()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
GLdouble w = glutGet( GLUT_WINDOW_WIDTH );
GLdouble h = glutGet( GLUT_WINDOW_HEIGHT );
glOrtho( 0, w, h, 0, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
// draw
if( !points.empty() )
{
glColor3ub( 255, 255, 255 );
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_COLOR_ARRAY );
glVertexPointer( 2, GL_FLOAT, sizeof( Point ), &points[ 0 ].x );
glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( Point ), &points[ 0 ].r );
glPointSize( 3.0 );
glDrawArrays( GL_POINTS, 0, points.size() );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
}
glutSwapBuffers();
}
void OnMouseClick( int button, int state, int x, int y )
{
if( button == GLUT_LEFT_BUTTON && state == GLUT_UP )
{
//store the x,y value where the click happened
Point p = Point();
p.x = (float)x;
p.y = (float)y;
p.r = 255;
p.g = 255;
p.b = 255;
p.a = 255;
points.push_back( p );
glutPostRedisplay();
}
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 500, 500 );
glutInitWindowPosition( 100, 100 );
glutCreateWindow( "OpenGL - Drawing points" );
glutDisplayFunc( drawPoints );
glutMouseFunc( OnMouseClick );
glutMainLoop();
return 0;
}
Trying to display the characters typed on keyboard, I am using the following code:
void myKey(unsigned char key, int x, int y)
{
if (key == 13) // enter key
{
return;
}
glRasterPos2f(xpos, 600);
glColor3f(0.0, 0.0, 1.0); // text color
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, key); // print the color
glFlush();
xpos += 15;
player1[i] = key;
i += 1;
}
It prints the text entered onto the screen but, it doesn't exit as it is supposed to when I press enter. I want the the code to display the player name of the player1 and store it in an array then exit when I press enter and then continue to accept the second player name.
Only do OpenGL stuff in the display callback.
You need to break your text entry into two pieces:
Keyboard/array handling in the glutKeyboardFunc() callback. Once you're done modifying the name list post a redisplay event.
String rendering in the glutDisplayFunc() callback, where you iterate over the name vector and display each string.
Like so:
#include <GL/freeglut.h>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
vector< string > names( 1 );
void keyboard( unsigned char key, int x, int y )
{
if( key == 13 )
{
// enter key
names.push_back( "" );
}
else if( key == 8 )
{
// backspace
names.back().pop_back();
}
else
{
// regular text
names.back().push_back( key );
}
glutPostRedisplay();
}
void display()
{
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
glOrtho( 0, w, 0, h, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
for( size_t i = 0; i < names.size(); ++i )
{
ostringstream oss;
oss << ( i + 1 ) << ": " << names[i];
void* font = GLUT_BITMAP_9_BY_15;
const int fontHeight = glutBitmapHeight( font );
glRasterPos2i( 10, h - ( fontHeight * ( i + 1 ) ) );
glutBitmapString( font, (const unsigned char*)( oss.str().c_str() ) );
}
glutSwapBuffers();
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "GLUT" );
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
glutMainLoop();
return 0;
}
how can drawing like square or TRIANGLES when clicked on any position on screen show the shape this is my Attempt i do't know what doing
...........................................................................
.......................................................................................
#include <windows.h>
#include <gl/Gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
GLsizei wh=500,ww=500;
GLfloat size=3.0;
void drawsquare( int x, int y)
{
y=wh-y;
glBegin(GL_POLYGON);
glVertex2f(x+size,y+size);
glVertex2f(x-size,y+size);
glVertex2f(x-size,y-size);
glVertex2f(x+size,y-size);
glEnd();
glFlush();
}
void mymose(int button,int state,int x,int y)
{
if(button==GLUT_LEFT_BUTTON && state==GLUT_DOWN)
drawsquare(x,y);
//if(button==GLUT_RIGHT_BUTTON_BUTTON && state==GLUT_UP)
// exit();
}
void myInit(){
glViewport(0,0,ww,wh);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,(GLdouble)ww,0.0,(GLdouble)wh);
glMatrixMode(GL_MODELVIEW);
glClearColor(0.0,0.0,0.0,1.0);
glColor3f(1.0,0.0,0.0);
}
int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA);
glutInitWindowSize(ww,wh);
glutInitWindowPosition(100,100);
glutCreateWindow("GLUT");
glutMouseFunc(mymose);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
You need a vector to store the points in.
Add points in the mouse callback and request a redraw via glutPostRedisplay().
Then in display() you can spin over all the points in the vector and draw quads around them:
#include <GL/glut.h>
#include <vector>
struct Point
{
Point( float x, float y ) : x(x), y(y) {}
float x, y;
};
std::vector< Point > points;
void mouse( int button, int state, int x, int y )
{
if( button == GLUT_LEFT_BUTTON && state == GLUT_UP )
{
points.push_back( Point( x, y ) );
}
if( button == GLUT_RIGHT_BUTTON && state == GLUT_UP )
{
points.clear();
}
glutPostRedisplay();
}
void display()
{
glClearColor( 0, 0, 0, 1 );
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
int w = glutGet( GLUT_WINDOW_WIDTH );
int h = glutGet( GLUT_WINDOW_HEIGHT );
glOrtho( 0, w, h, 0, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glColor3ub( 255, 0, 0 );
glBegin( GL_QUADS );
for( size_t i = 0; i < points.size(); ++i )
{
const unsigned int SIZE = 20;
const Point& pt = points[ i ];
glVertex2i( pt.x - SIZE, pt.y - SIZE );
glVertex2i( pt.x + SIZE, pt.y - SIZE );
glVertex2i( pt.x + SIZE, pt.y + SIZE );
glVertex2i( pt.x - SIZE, pt.y + SIZE );
}
glEnd();
glutSwapBuffers();
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "GLUT" );
glutMouseFunc( mouse );
glutDisplayFunc( display );
glutMainLoop();
return 0;
}
Quick question:
How can I draw value of double using
glutBitmapCharacter
?
I tried many options but none of them works, I don't know how to convert double to char *
#include <GL/glut.h>
#include <sstream>
#include <iomanip>
void glString( const std::string str, void* font = GLUT_BITMAP_8_BY_13 )
{
for( size_t i = 0; i < str.size(); ++i )
{
glutBitmapCharacter( font, str[i] );
}
}
void display()
{
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
glOrtho( 0, w, h, 0, -1, 1);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glColor3ub( 255, 255, 255 );
glRasterPos2i( 50, 50 );
double val = 3.14159265358979323846;
std::ostringstream oss;
oss << std::setprecision(17) << val;
glString( oss.str() );
glutSwapBuffers();
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "Text" );
glutDisplayFunc( display );
glutMainLoop();
return 0;
}