suspend a function for sometime in opengl - opengl

I have a function Drwa() this is rendering a triangle on screen.and also i have another Draw_poly() which is rendering a Rectangle on screen. And i also i m rotating rectangle and triangle both simultaneously.I want to keep speed of rotation different for both how will i do ?
Let suppose i am moving an object on screen and another i m rotating then how will i do ? That's why i m looking for function moving of object will keep time limited and rotating object will not keep time.So rotation will be fast and moving of object will be slow

First, define your rotation as angle per second. Then in your main draw function, compute the elapsed time in second, multiply by the angular speed, and you're done.

I would like to partecipate with a an answer of mine.
The answer of genpfault could be good as much as you need, but if you would like to produce a good animation you need to design a better software.
Here, look at my answer. However, reading another your question, I think you are missing some fundamental point: learn OpenGL architecture, practice on each OpenGL entry point, read books.
At last, but not least, I would you suggest to search for answer already told on stackoverflow. This is supposed to be a question & answer site...

Rotate one less/slower than the other:
static float rot_a = 0.0;
static float rot_b = 0.0;
rot_a += 1.0;
rot_b += 0.5;
glPushMatrix();
glRotatef( rot_a, 0, 0, 1 );
Draw_A();
glPopMatrix();
glPushMatrix();
glRotatef( rot_b, 0, 0, 1 );
Draw_B();
glPopMatrix();
Alternatively you can spin up some threads that modify your object positions and sleep() without blocking the render thread.
Position obj_a;
Position obj_b;
void thread_1()
{
while( !done )
{
sleep(1);
modify_pos( obj_a );
}
}
void thread_2()
{
while( !done )
{
sleep(2);
modify_pos( obj_b );
}
}
void draw()
{
glPushMatrix();
position_object( obj_a );
Draw_A();
glPopMatrix();
glPushMatrix();
position_object( obj_b );
Draw_B();
glPopMatrix();
}
int main()
{
...
launch_thread( thread_1 );
launch_thread( thread_2 );
...
return 0;
}

Related

OGLFT draws text when GLStipple is used

I have an interesting bug that has been "bugging" me for a few days now.
I am currently using OpenGL to draw text on a screen. I am utilizing the OGLFT library to assist the drawing. This library actually uses the freetype2 library. I am actually not doing anything special with the text. I am only looking for monochromatic text.
Anyways, after implementing the library, I noticed that the text is only drawn correct when I have glStipple enabled. I believe that there is some interference issue between the OGLFT library and what I am enabling.
I was wondering if there is anyone out there with some experience on using the OGLFT library. I am posting a minimalist example of my code to demonstrate what is going on:
(Please note that there are some variables that are used to st the zoom factor of my glCanvas and the position of the camera and that this is only for 2D)
double _zoomX = 1.0;
double _zoomY = 1.0;
double _cameraX = 0;
double _cameraY = 0;
/* This function gets called everytime a draw routine is needed */
void modelDefinition::onPaintCanvas(wxPaintEvent &event)
{
wxGLCanvas::SetCurrent(*_geometryContext);// This will make sure the the openGL commands are routed to the wxGLCanvas object
wxPaintDC dc(this);// This is required for drawing
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
updateProjection();
OGLFT::Monochrome *testface = new OGLFT::Monochrome( "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 8);
testface->draw(0, 0, "test");
glEnable(GL_LINE_STIPPLE);// WHen I comment out this line, the text is unable to be drawn
glLineStipple(1, 0b0001100011000110);
glBegin(GL_LINES);
glVertex2d(_startPoint.x, _startPoint.y);
glVertex2d(_endPoint.x, _endPoint.y);
glEnd();
glDisable(GL_LINE_STIPPLE);
SwapBuffers();
}
void modelDefinition::updateProjection()
{
// First, load the projection matrix and reset the view to a default view
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-_zoomX, _zoomX, -_zoomY, _zoomY, -1.0, 1.0);
//Reset to modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, (double)this->GetSize().GetWidth(), (double)this->GetSize().GetHeight());
/* This section will handle the translation (panning) and scaled (zooming).
* Needs to be called each time a draw occurs in order to update the placement of all the components */
if(_zoomX < 1e-9 || _zoomY < 1e-9)
{
_zoomX = 1e-9;
_zoomY = _zoomX;
}
if(_zoomX > 1e6 || _zoomY > 1e6)
{
_zoomX = 1e6;
_zoomY = _zoomX;
}
glTranslated(-_cameraX, -_cameraY, 0.0);
}
Also one thing to note is that the code below the glEnable(GL_LINE_STIPPLE); is required. It is as if the glStipple needs to be drawn correctly for the text to be displayed correctly.
Looking through your code, I believe that your intention is to render it as a greyscale? If so, then you can simply use the OGLFT::Grayscale *testface = new OGLFT::Grayscale( "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 8);
This will get what you need without having to worry about the issue that you posted. In fact, I recommend doing it this way too.

gluLookAt() not looking where it should

I don't understand what the glLookAt() function does exactly.
I have an object at position x,y,z . I want to place the camera at position x+20,y+20,z+20 while the object is moving, so that it should look like stationary. However, this is not the case : when I do the following code, I see a cross which is slowly moving to the right and even goes out of the window !
while (keystate[SDLK_ESCAPE] == false) {
SDL_PollEvent(&event);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
n+=0.1;
float x = 10;
float y = 10+n*n;
float z = 10;
// drawing an object at x,y,z (here a cross)
glBegin(GL_LINES);
glColor3ub(200,0,0);
glVertex3f(x-2,y,z);
glVertex3f(x+2,y,z);
glVertex3f(x,y-2,z);
glVertex3f(x,y+2,z);
glEnd();
// looking at the object
glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
gluLookAt(x+20,y+20,z+20,x,y,z,0,0,1);
glFlush();
SDL_GL_SwapBuffers();
}
If the camera were correctly looking at x,y,z , the cross should always appear at the center ?
If I put y = 10 + n , the object looks stationary.
With y = 10 + n * n , the object moves at constant speed, and with y = 10 + n * n * n, the object moves and accelerates.
I also did
gluPerspective(70,(double)640/480,1,1000);
at the beginning of my code.
Thank you in advance ! :S
OpenGL is a state machine, not a scene graph library. It does not remember the objects you have drawn. With your code, you first draw the object (with whatever matrices are current), and after that, set the new view matrix. This will have no effect on the object already drawn during this frame.
When the above code is executed in a loop, this will have the effect that the camera always looks at the object's position from last frame, and as faster your object is moving, the more away from the camera it will get.
Set the matrices before you draw the object.

Mouse-drag object in OpenGL/GLUT [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 9 years ago.
Improve this question
I have been searching all day for a tutorial or example code for a simple program - click on object (like a 2D rectangle for example) then as you hold and move the mouse the object follows the mouse, then on mouse release the object remains in new location. In other words, I want to understand how to drag and drop an object with the mouse events.
Could anyone help to point me in the right direction of any useful sources of information relating to this problem?
Thanks for all the responses so far.
I have worked out how to do it, so I will go ahead an answer my own question.
I am using GLUT as a mouse handler:
When the mouse is clicked and moving (glutMotionFunc) the drag function is called.
In the drag function the mouse coordinates (x,y) are converted to a Points struct while being converted into window coordinates.
If the mouse is within the square then drag the square by changing it's coordinates and redisplay.
I am still very new to OpenGL and C++ so I do apologize for the messy coding. I am a bit frustrated in doing it this way as the redrawn square makes it seem the cursor snaps to the center. I welcome alternative solutions to this problem and criticism of my code, for learning purposes.
CODE (included glut and using namespace std):
// points structure made of two coordinates; x and y
struct Points
{
float x,y; // initializor
Points() { x = 0.0; y = 0.0; } // constructor
Points(float _x, float _y) : x(_x), y(_y) {}
};
// square made of 4 points
class Square
{
public:
Points pts[4]; // square structure
Square(); // initialize constructor
void draw(Square *sqr); // draw square
Points mouse(int x, int y); // get mouse coordintaes
Square* drag(Square *sqr, Points *mouse); // change points of sqr
};
// square constructor
Square::Square()
{
pts[0] = Points(0.2,0.2);
pts[1] = Points(0.4,0.2);
pts[2] = Points(0.4,0.4);
pts[3] = Points(0.2,0.4);
};
// draw function
void Square::draw(Square *sqr)
{
// draw square fill
int i;
glColor3f(0.2, 0.2, 0.2);
glBegin(GL_QUADS);
for (i = 0; i < 4; ++i)
{
glVertex2f(sqr->pts[i].x, sqr->pts[i].y);
}
glEnd();
// draw square points
i = 0;
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_POINTS);
for (i = 0; i < 4; ++i)
{
glVertex2f(sqr->pts[i].x, sqr->pts[i].y);
}
glEnd();
}
// mouse function
Points Square::mouse(int x, int y)
{
int windowWidth = 400, windowHeight = 400;
return Points(float(x)/windowWidth, 1.0 - float(y)/windowHeight);
}
// drag function
Square* Square::drag(Square *sqr, Points *mouse)
{
sqr->pts[0].x = mouse->x - 0.1;
sqr->pts[0].y = mouse->y - 0.1;
sqr->pts[1].x = mouse->x + 0.1;
sqr->pts[1].y = mouse->y - 0.1;
sqr->pts[3].x = mouse->x - 0.1;
sqr->pts[3].y = mouse->y + 0.1;
sqr->pts[2].x = mouse->x + 0.1;
sqr->pts[2].y = mouse->y + 0.1;
return sqr;
}
// GLOBAL
// create square object
Square* sqr = new Square;
// display at start
void display() {
glClear(GL_COLOR_BUFFER_BIT);
sqr->draw(sqr);
glFlush();
}
// drag function
void drag (int x, int y)
{
// int x and y of mouse converts to screen coordinates
// returns the point as mousePt
Points mousePt = sqr->mouse(x,y);
//create pointer to window point coordinates
Points* mouse = &mousePt;
// if the mouse is within the square
if (mouse->x > sqr->pts[0].x && mouse->y > sqr->pts[0].y)
{
if (mouse->x < sqr->pts[2].x && mouse->y < sqr->pts[2].y)
{
// then drag by chaning square coordinates relative to mouse
sqr->drag(sqr,mouse);
glutPostRedisplay();
}
}
}
void Initialize() {
glClearColor(0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
}
int main(int iArgc, char** cppArgv) {
glutInit(&iArgc, cppArgv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(400, 400);
glutInitWindowPosition(200, 200);
glutCreateWindow("Move Box");
glutMotionFunc(drag);
Initialize();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
OpenGL is only concerned with the drawing process. Everything else (mouse input, object picking, scene management/alterations, etc.) is completely up to you to implement.
Here's a rough outline:
Install a mouse click event handler (the exact method to use depends on the framework used and/or the operating system)
In the mouse click event handler perform a picking operation. This usually involves unprojecting the mouse window position into the world space (see gluUnproject) resulting in a ray. Test each object in the scene if it intersects with the ray; you'll have to implement this yourself, because OpenGL just draws thing (there is no such thing as a "scene" in OpenGL).
If a object has been picked register it to be manipulated in the mouse drag handler
everytime a mouse drag event happens adjust the object's position data and trigger of the OpenGL display (you always redraw the whole thing in OpenGL).
When the mouse is released unregister the object from the drag handler.
As mentioned by others, OpenGL does not handle user input. You want to use a library for that. If you want a more all-around solution, you can even use a more complete render or physics engine.
For simple user input, you can use SDL (e.g. this is for mouse input).
For more complete 2D stuff, you can just use Box2D. Here are a whole bunch of tutorials.
The heavy-weight solution is a complete render engine, such as Ogre3D or CrystalSpace.
As mentioned by others, you need to get a mouse handler to get the mouse position first. Then you need a way to pick an object. You have a few options to do the picking in OpenGL.
If you are using classic OpenGL, you can use the select buffer. The following link is a good tutorial
http://www.lighthouse3d.com/opengl/picking/index.php3?openglway
If you are using modern opengl, which is shader based, you can use FBO based picking.
http://ogldev.atspace.co.uk/www/tutorial29/tutorial29.html
You can always implement a ray tracking picking yourself in both cases. The gluUnproject can help a lot in the implementation.
http://schabby.de/picking-opengl-ray-tracing/
After that, you just need to update the object position according to the mouse movement or acceleration.

OpenGL glViewport() (resetting coordinates)

I have a problem with glViewport. In my liitle programm i have two viewports. I can draw a form (with the motionfunc) in one of those viewports and in the other a line is automatically drawn.
So far so good..
When i try to draw something with mousefunc the viewport is in a total different place. And it is very difficult to find the new correct coordinates for that viewport.
Is there a possibility to reset the coordinates..
I cant use glLoadIdentity in mouse or motion because then nothing is displayed.
I hope you understand what i mean. It is a bit difficult to explain.
OK here a codesnippet....
void mouse (int button, int state, int mx, int my)
{
if (modus == 0 && button==GLUT_LEFT_BUTTON && state != GLUT_DOWN)
{
...
}
else if (modus == 1 && button==GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
**glViewport(10,10 , sw_w1, sw_h1);**
//the drawing is much higher than in the first viewport in motion.
//But it should be the same viewport like the first in motion.
glBegin()...glEnd()
glFlush();
}
}
void motion(int mousex,int mousey)
{
GLdouble h=12;
GLdouble winkel=360/h;
Line liste[num];
liste[++last].x =(mousex)-((sw_w1+2*GAP)/2);
liste[last].y =(mousey)-((sw_h1+2*GAP)/2);
if (modus==0 && gruppe == 0) {
if (last>=1)
{
glViewport(10, 10, sw_w1, sw_h1); //works fine
glColor3d(R, G, B);
for(h+1;h>0;h--){
glRotated(winkel, 0, 0, 1);
glBegin(GL_LINE_STRIP);
for(int i=last-1;i<=last;i++){
glVertex2i(liste[i].x,liste[i].y);
}
glEnd();
}
glLineWidth(linewidth+0.5);
glColor3f(1, 0, 0);
glBegin(GL_LINE_STRIP);
for(int i=last-1;i<=last;i++){
glVertex2i(liste[i].x,liste[i].y);
}
glEnd();
glViewport(1020,10 , sw_w2, sw_h2); //works fine
glColor3f(1, 0, 0);
glBegin(GL_LINE_STRIP);
for(int i=last-1;i<=last;i++){
glVertex2i(liste[i].x,liste[i].y);
}
glEnd();
}
glFlush();
}
}
The second and third viewport works fine. The first one is the same as the second but the picture is displayed much higher.Why is that so?
And how could i change it so that i get the same viewport like the second one.
I hope you now understand what i mean.
You should check your modelview/projection matrices and see if they are what you expect them to be in each function.
Also, as Christian's commented, it is not necessary, nor recommended, to draw in the motion func. Update your application state per the input and call glutPostRedisplay to signal that you want to redraw your window. That way, your application will have a cleaner design and it will be easier to make it behave consistently.
(added my comment as answer since that was the problem, and added Christian's comment, since that is the proper solution. Don't draw in motionfunc!.)

Limit Speed Of Gameplay On Different Computers

I'm creating a 2D game using OpenGL and C++.
I want it so that the game runs at the same speed on different computers, At the moment my game runs faster on my desktop than my laptop (i.e. my player moves faster on my desktop)
I was told about QueryPerformanceCounter() but I don't know how to use this.
how do I use that or is there a better/easier way?
My Display function
void display()
{
static long timestamp = clock();
// First frame will have zero delta, but this is just an example.
float delta = (float)(clock() - timestamp) / CLOCKS_PER_SEC;
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
createBackground();
int curSpeed = (player.getVelocity()/player.getMaxSpeed())*100;
glColor3f(1.0,0.0,0.0);
glRasterPos2i(-screenWidth+20,screenHeight-50);
glPrint("Speed: %i",curSpeed);
glRasterPos2i(screenWidth-200,screenHeight-50);
glPrint("Lives: %i",lives);
glRasterPos2i(screenWidth-800,screenHeight-50);
glPrint("Heading: %f",player.getHeading());
for(int i = 0;i<90;i++){
if (numBullets[i].fireStatus == true){
numBullets[i].updatePosition(player);
if (numBullets[i].getXPos() > screenWidth || numBullets[i].getXPos() < -screenWidth || numBullets[i].getYPos() > screenHeight || numBullets[i].getYPos() < -screenHeight ){
numBullets[i].fireStatus = false;
numBullets[i].reset(player);
numBullets[i].~Bullet();
}
}
}
player.updatePosition(playerTex,delta);
glFlush();
timestamp = clock();
}
My Update positiom method
void Player::updatePosition(GLuint playerTex, float factor){
//draw triangle
glPushMatrix();
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, playerTex);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTranslatef(factor*XPos, factor*YPos, 0.0);
glRotatef(heading, 0,0,1);
glColor3f(1.0,0.0,0.0);
glBegin(GL_POLYGON);
glTexCoord2f(0.0, 1.0); glVertex2f(-40,40);
glTexCoord2f(0.0, 0.0); glVertex2f(-40,-40);
glTexCoord2f(1.0, 0.0); glVertex2f(40,-40);
glTexCoord2f(1.0, 1.0); glVertex2f(40,40);
glEnd();
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glPopMatrix();
XPos += speed*cos((90+heading)*(PI/180.0f));
YPos += speed*sin((90+heading)*(PI/180.0f));
}
As a rule, you want to do all gameplay calculations based on a time delta, i.e. the amount of time that has passed since the last frame. This will standardize speed on all machines. Unless you want extreme precision, you can use clock() (from <ctime>) to get the current timestamp.
Example:
void main_loop() {
static long timestamp = clock();
// First frame will have zero delta, but this is just an example.
float delta = (float)(clock() - timestamp) / CLOCKS_PER_SEC;
calculate_physics(delta);
render();
timestamp = clock();
}
void calculate_physics(float delta) {
// Calculate expected displacement per second.
applyDisplacement(displacement * delta);
}
void render() {
// Do rendering.
}
EDIT: If you want higher precision, you should use your OS timer features. On Windows, the most precise method is using QueryPerformanceCounter(). Example
#include <windows.h>
void main_loop(double delta) {
// ...
}
int main() {
LARGE_INTEGER freq, last, current;
double delta;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&last);
while (1) {
QueryPerformanceCounter(&current);
delta = (double)(current.QuadPart - last.QuadPart) / (double)freq.QuadPart;
main_loop(delta);
last = current;
}
}
Most games use a frame time-scaling factor. Essentially, you find the length of the frame your physics and movement are set at and divide it between the actual length of the frame the game is running at (1/fps). This produces a scalar factor which you can multiply by changes in movement to keep all movements consistent while maintaining the benefits from increasing the FPS.
A good example is here.
The best solution to your problem is to only update the positions of your objects once every 10 ms (or something similar) but render the objects as often as possible. This is called "fixed time step" as you only update the game state at fixed intervals. This requires you to decouple the rendering code from the update code (which is a good idea anyway).
Basically (in psudoe code) what you would do is something like:
accumulatedTimeSinceLastUpdate = 0;
while(gameIsRunning)
{
accumulatedTimeSinceLastUpdate += timeSinceLastFrame();
while(accumulatedTimeSinceLastUpdate >= 10) // or another value
{
updatePositions();
accumulatedTimeSinceLastUpdate -= 10;
}
display();
}
This means that if your computer is running super-duper fast display() will be called a lot of times and every now and then updatePositions(). If your computer is ultra slow updatePositions may be called several times for each time display() is called.
Here's another good read (in addition to Mason Blier's):
http://gafferongames.com/game-physics/fix-your-timestep/