Memory leak when using freetype library - c++

In the following code snippet, I am leaking 52 bytes of memory for every iteration of the for loop, but after several hours I am unable to determine why =/
Any help will be appreciated.
for(unsigned char i=0; i<128; ++i)
{
ttf.loadGlyph(i);
FT_Glyph glyph;
FT_Get_Glyph(ttf.ftFace_->glyph, &glyph);
FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1 );
FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;
FT_Bitmap& bitmap = bitmap_glyph->bitmap;
int width = nextPowerOf2(bitmap.width);
int height = nextPowerOf2(bitmap.rows);
GLubyte* expanded_data = new GLubyte[ 2 * width * height]; // Allocate Memory For The Texture Data.
for(int j=0; j <height;j++) {
for(int i=0; i < width; i++){
expanded_data[2*(i+j*width)]= expanded_data[2*(i+j*width)+1] =
(i>=bitmap.width || j>=bitmap.rows) ?
0 : bitmap.buffer[i + bitmap.width*j];
}
}
glBindTexture( GL_TEXTURE_2D, fontData_.pTextures_[i]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data );
delete [] expanded_data;
glNewList(fontData_.fontBase_+i, GL_COMPILE);
glBindTexture(GL_TEXTURE_2D, fontData_.pTextures_[i]);
glPushMatrix();
glTranslatef( (GLfloat)bitmap_glyph->left, 0.0f, 0.0f );
glTranslatef(0.0f, (GLfloat)bitmap_glyph->top-bitmap.rows, 0.0f);
float x=(float)bitmap.width / (float)width,
y=(float)bitmap.rows / (float)height;
glBegin(GL_QUADS);
glTexCoord2d(0,0); glVertex3f( 0, 0, 1 ); //Bottom-left vertex (corner)
glTexCoord2d(0,y); glVertex3f( 0, (GLfloat)bitmap.rows, 1 ); // top left vertex
glTexCoord2d(x,y); glVertex3f( (GLfloat)bitmap.width, (GLfloat)bitmap.rows, 1 ); // top right vertex
glTexCoord2d(x,0); glVertex3f( (GLfloat)bitmap.width, 0, 1 ); // bottom right
glEnd();
glPopMatrix();
glTranslatef( (GLfloat)( ttf.ftFace_->glyph->advance.x >> 6 ), 0, 0);
glEndList();
}

From the docs:
FT_Get_Glyph
A function used to extract a glyph image from a slot. Note that the
created FT_Glyph object must be released with FT_Done_Glyph.

Related

OpenGl draw on top of tile map C++

I am new to OpenGL. I have the following code that I am using from a tutorial I followed, what it does is render a tile map. It does this successfully but my problem now is that I want to add a moveable object onto the window however it is not appearing.
#include "stdafx.h"
#include <string>
#include <windows.h>
#include <iostream>
#include <conio.h>
#include <sstream>
#include <math.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include "GL/freeglut.h"
#pragma comment(lib, "OpenGL32.lib")
// window size and update rate (60 fps)
int width = 700;
int height = 700;
int interval = 1000 / 60;
// ball
float ball_pos_x = width / 2;
float ball_pos_y = height / 2;
float ball_dir_x = -1.0f;
float ball_dir_y = 0.0f;
int ball_width = 20;
int ball_height = 20;
int ball_speed = 5;
GLuint texture; //the array for our texture
GLuint texture2; //the array for our second texture
void keyboard() {
if (GetAsyncKeyState(VK_LEFT)) ball_pos_x -= ball_speed;
if (GetAsyncKeyState(VK_RIGHT)) ball_pos_x += ball_speed;
if (GetAsyncKeyState(VK_UP)) ball_pos_y += ball_speed;
if (GetAsyncKeyState(VK_DOWN)) ball_pos_y -= ball_speed;
}
int cMap[30][30] = { //our map
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};
void drawRect(float x, float y, float width, float height) {
glBegin(GL_QUADS);
glVertex2f(x, y);
glVertex2f(x + width, y);
glVertex2f(x + width, y + height);
glVertex2f(x, y + height);
glEnd();
}
GLuint LoadTexture( const char * filename, int width, int height )
{
GLuint texture;
unsigned char * data;
FILE * file;
//The following code will read in our RAW file
file = fopen( filename, "rb" );
if ( file == NULL ) return 0;
data = (unsigned char *)malloc( width * height * 3 );
fread( data, width * height * 3, 1, file );
fclose( file );
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
GL_MODULATE ); //set texture environment parameters
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR );
//Here we are setting the parameter to repeat the texture
//instead of clamping the texture
//to the edge of our shape.
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
GL_REPEAT );
//Generate the texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
GL_RGB, GL_UNSIGNED_BYTE, data);
free( data ); //free the texture
return texture; //return whether it was successfull
}
void FreeTexture( GLuint texture )
{
glDeleteTextures( 1, &texture );
}
void drawTiles (void) { //our function to draw the tiles
for (int i = 0; i < 10; i++) //loop through the height of the map
{
for (int j = 0; j < 10; j++) //loop through the width of the map
{
if (cMap[i][j] == 0) //if the map at this position contains a 0
{
glBindTexture( GL_TEXTURE_2D, texture ); //bind our grass texture to our shape
}
else //otherwise
{
glBindTexture( GL_TEXTURE_2D, texture2 ); //bind our dirt texture to our shape
}
glPushMatrix(); //push the matrix so that our translations only affect this tile
glTranslatef(j, -i, 0); //translate the tile to where it should belong
glBegin (GL_QUADS); //begin drawing our quads
glTexCoord2d(0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0); //with our vertices we have to assign a texcoord
glTexCoord2d(1.0, 0.0);
glVertex3f(1.0, 0.0, 0.0); //so that our texture has some points to draw to
glTexCoord2d(1.0, 1.0);
glVertex3f(1.0, 1.0, 0.0);
glTexCoord2d(0.0, 1.0);
glVertex3f(0.0, 1.0, 0.0);
glEnd();
glPopMatrix(); //pop the matrix
} //end first loop
} //end second loop
}
void draw() {
// clear (has to be done at the beginning)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); // ToDo: draw our scene
// draw ball
drawRect(ball_pos_x - ball_width / 2, ball_pos_y - ball_height / 2, ball_width, ball_height);
glEnable( GL_TEXTURE_2D );
glTranslatef(-5, 4, -20); //translate back a bit to view the map correctly
drawTiles(); //draw our tiles
// swap buffers (has to be done at the end)
glutSwapBuffers();
}
void UpdatePlayer(){
// hit by right racket?
if (ball_pos_x < ball_pos_x + ball_width &&
ball_pos_x > enemy_pos_x &&
ball_pos_y < enemy_pos_y + enemy_height &&
ball_pos_y > enemy_pos_y) {
ball_pos_x = ball_pos_x;
ball_pos_y = ball_pos_y;
}
}
void update(int value) { // Call update() again in 'interval' milliseconds
// input handling
keyboard();
UpdatePlayer();
glutTimerFunc(interval, update, 0);
// Redisplay frame
glutPostRedisplay();
}
void enable2D(int width, int height) {
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, width, 0.0f, height, 0.0f, 1.0f);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
}
void reshape (int w, int h) {
glViewport (0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
glMatrixMode (GL_MODELVIEW);
}
int _tmain(int argc, char** argv)
{
// initialize opengl (via glut)
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(width, height); glutCreateWindow("noobtuts.com Pong");
// Register callback functions
glutDisplayFunc(draw);
glutIdleFunc (draw);
glutReshapeFunc (reshape);
glutTimerFunc(interval, update, 0);
// setup scene to 2d mode and set draw color to white
enable2D(width, height);
glColor3f(1.0f, 1.0f, 1.0f);
//Load our texture
texture = LoadTexture("texture.raw", 256, 256);
texture2 = LoadTexture("texture2.raw", 256, 256);
glutMainLoop ();
//Free our texture
FreeTexture(texture);
FreeTexture(texture2);
return 0;
}
If I was to comment out in the main...
glutIdleFunc (draw);
glutReshapeFunc (reshape);
The tile map will disappear and my moveable square is visible and works...I just can't implement the two together successfully. Again i'm completely new to this so apologise if I am doing something really stupid Any ideas where I am going wrong?
Are you sure you want to draw the tile map with a perspective projection? It seems to me that you should be using an orthographic projection for both the tile map and the ball.
Change your reshape function to simply call enable2D(w, h). Then change your drawTiles function to draw using screen coordinates instead. That should work.
Some additional notes:
Don't forget to disable texturing when drawing your ball (you don't seem to be setting any texture for it, so it will just render with the last texture set).
You could also disable depth testing with glDisable(GL_DEPTH_TEST) since you don't really need it (and use glVertex2f for drawing the tile map instead of glVertex3f)

PNG to Opengl usage issues

I'm trying to collate several native PNG images into Opengl & I'm having some roadblocks. I'm already using a Cximage library, so would prefer to stick to this if I can help it.
3 related issues;
PNGs are showing as black & white in OpenGL. The image isn't the issue as Other image types work but I'd rather not convert unless it's easy & doesn't require disk saving or another library.
PNG having black background which are suppose to be transparent.
OpenGL view/Orientation issue. Image is skewed in OpenGL ie not orientated properly. The PNGs contain isometric views, which I'm trying to display.
Sample of code I am currently using;
*And Yes I realise I'm using depreciated Opengl. I need to due to legacy code I am working with.
int MyScene::LoadTexture
{
m_pImgCol = new CxImage((BYTE *)pdatabuffer, (DWORD)filesize, CXIMAGE_FORMAT_PNG);
DWORD iDest(0), iSrc(0);
DWORD dwSize = m_pImgCol->GetWidth()*m_pImgCol->GetHeight();
BYTE *pSrc = m_pImgCol->GetBits();
BYTE *pDest = new BYTE[dwSize * 4];
BYTE *pSrcA = m_pImgAlpha ? m_pImgAlpha->GetBits() : NULL;
BYTE alpha;
for (DWORD iX = 0; iX<dwSize; iX++)
{
alpha = 255;
if (pSrcA)
alpha = pSrcA[iX];
else
{
if (pSrc[iSrc] == 0 && pSrc[iSrc + 1] == 0 && pSrc[iSrc + 2] == 0)
alpha = 0;
}
pDest[iDest++] = pSrc[iSrc++];
pDest[iDest++] = pSrc[iSrc++];
pDest[iDest++] = pSrc[iSrc++];
pDest[iDest++] = alpha;
}
GLuint iTexture=0;
glGenTextures(1, &iTexture);
glBindTexture(GL_TEXTURE_2D, 0);
glTexImage2D(GL_TEXTURE_2D, 0, 4, m_pImgCol->GetWidth(), m_pImgCol->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, pDest);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glEnable(GL_TEXTURE_2D);
}
int MyScene::DrawGLScene()
{
CRect rWnd;
GetClientRect(&rWnd);
glViewport(0,0,rWnd.Width(),rWnd.Height());
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-20 * m_Zoom, 20 * m_Zoom, -15 * m_Zoom, 25 * m_Zoom, 20000, -20000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glTranslatef(0, -0.5f, 0.0f);
glRotatef(m_rx, 1.0f, 0.0f, 0.0f);
glRotatef(m_rz, 0.0f, 0.0f, 1.0f);
glRotatef(m_ry, 0.0f, 1.0f, 0.0f);
DrawScene();
SwapBuffers(m_pView->m_hDC);
return TRUE;
}
int MyScene::DrawScene
{
float dL = -8;
float dR = 8;
float dT = -8;
float dB = 8;
glBindTexture(GL_TEXTURE_2D, 0);
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glVertex3f(dL, dT, 0);
glTexCoord2f(0, 0);
glVertex3f(dL, dB, 0);
glTexCoord2f(0, 1);
glVertex3f(dR, dB, 0);
glTexCoord2f(1, 1);
glVertex3f(dR, dT, 0);
glTexCoord2f(1, 0);
glEnd();
}
If necessary I can provide more code, but this is as basic as I can break it down to.
Found http://ysflight.in.coocan.jp/programming/pngdecoder/pngdecodere.html & modified it to read existing buffer. Minimal fuss, no disk saving or library.
got PNG transparency working by adding;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Imaging tearing; seems I had following in wrong order;
glTexCoord2f(0, 0);
glVertex3f(dL, dT, 0);

C++ OpenGL Bitmap transparency issues

I started with opengl texturing and everything was working well. Now I am trying to load a bmp and make white part transparent using glEnable(GL_BLEND); and glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
This is my source code:
float kSpeedForw=0.0f;
GLuint texture[1];
CCamera g_Camera;
GLfloat xrot = 0;
GLfloat yrot = 0;
GLfloat zrot = 0;
bool g_bFullScreen = true;
HWND g_hWnd;
RECT g_rRect;
HDC g_hDC;
HGLRC g_hRC;
HINSTANCE g_hInstance;
float jump = -0.1;
GLfloat LightAmbient[] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f, 1.0f };
void Init(HWND hWnd)
{
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light
glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); // Position The Light
glEnable(GL_LIGHT1); // Enable Light One
glColor4f(1.0f, 1.0f, 1.0f, 0.5); // Full Brightness. 50% Alpha
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
g_hWnd = hWnd;
GetClientRect(g_hWnd, &g_rRect);
InitializeOpenGL(g_rRect.right, g_rRect.bottom);
g_Camera.PositionCamera(0, 1.5f, 6, 0, 1.5f, 5, 0, 1, 0);
ShowCursor(false);
}
GLuint LoadTexture(const char * filename)
{
glEnable(GL_TEXTURE_2D);
GLuint texture;
int width, height;
unsigned char * data;
FILE * file;
file = fopen(filename, "rb");
if (file == NULL) return 0;
if (filename=="Data/weed.bmp"){
width = 200;
height = 200;
}
if (filename == "Data/gun.bmp"){
width = 300;
height = 300;
}
data = (unsigned char *)malloc(width * height * 3);
fread(data, width * height * 3, 1, file);
fclose(file);
for (int i = 0; i < width * height; ++i)
{
int index = i * 3;
unsigned char B, R;
B = data[index];
R = data[index + 2];
data[index] = R;
data[index + 2] = B;
}
if (filename == "Data/weed.bmp"){
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, data);
free(data);
}
if (filename == "Data/gun.bmp"){
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 3,width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
}
return texture;
}
WPARAM MainLoop() // main function
{
MSG msg;
Init(g_hWnd);
glClearColor(0, 0, 255, 0);
while (1)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else if (LockFrameRate(60))
{
g_Camera.SetViewByMouse();
kSpeedForw = 0;
if (jump > -0.1)jump-=0.01;
CheckForMovement();
g_Camera.MoveCamera(kSpeedForw, jump);
RenderScene();
}
}
DeInit();
return(msg.wParam);
}
void RenderScene()
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glDisable(GL_BLEND);
glEnable(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(g_Camera.m_vPosition.x, g_Camera.m_vPosition.y, g_Camera.m_vPosition.z,
g_Camera.m_vView.x, g_Camera.m_vView.y, g_Camera.m_vView.z,
g_Camera.m_vUpVector.x, g_Camera.m_vUpVector.y, g_Camera.m_vUpVector.z);
GLuint texture;
texture = LoadTexture("Data/weed.bmp");
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_QUADS);
float i = 0;
glColor3f(1,1,1);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-10 + i / 5, 0, 10 - i / 5);
glTexCoord2f(50.0f, 0.0f);
glVertex3f(-10 + i / 5, 0, -10 + i / 5);
glTexCoord2f(50.0f, 50.0f);
glVertex3f(10 - i / 5, 0, -10 + i / 5);
glTexCoord2f(0.0f, 50.0f);
glVertex3f(10 - i / 5, 0, 10 - i / 5);
glEnd();
////////////////////////////////////////////////////////////HUD
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SMOOTH);
glEnable(GL_BLEND); // Turn Blending On
int vPort[4];
glGetIntegerv(GL_VIEWPORT, vPort);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, vPort[2], 0, vPort[3], -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
GLuint ruka;
ruka = LoadTexture("Data/gun.bmp");
glBindTexture(GL_TEXTURE_2D, ruka);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(0, 0);
glTexCoord2f(1.0f, 0.0f);
glVertex2f(450,0);
glTexCoord2f(1.0f, 1.0f);
glVertex2f(450,450);
glTexCoord2f(0.0f, 1.0f);
glVertex2f(0,450);
glEnd();
SwapBuffers(g_hDC);
}
The code works well for loading and rendering the platform(weed.bmp) and it also loads and renders gun fine. But big part of gun.bmp is white. I was hoping to get that part transparent. I was also hoping to add more HUD features, which would also need to be partly transparent.
My gun.bmp file: https://drive.google.com/file/d/0BxxlNcAI0eh9cHZGd1ZfMTFwYmM/view?usp=sharing
If you know a solution of this problem please post it. Thanks
You load image as GL_RGB, you want GL_RGBA to have an alpha channel.
Also, you need a 32 bits Bitmap (8 bits/channel × 4 channels = 32 bits).

My code fails to load picture into opengl properly

I tried to load the six pictures as texture and draw a skybox, but the result is weird, each picture is mapped three times on its corresponding rectangle in grey. What is the problem?
#include <stdlib.h>
#include <stdio.h>
#include <glut.h>
#include <gl.h>
#include <glu.h>
#include <math.h>
#include <windows.h>
GLuint texture [6]; //the array for our texture
void init(void)
{
glClearColor (0.0, 0.0, 0.0, 1.0);
glShadeModel (GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
glEnable(GL_TEXTURE_2D);
}
GLuint LoadTexture( const char * filename, int width, int height) {
GLuint texture;
unsigned char * data;
FILE* file;
file = fopen( filename, "r" );
if ( file == NULL ) return 0;
data = (unsigned char *)malloc( width * height * 3 );
fread( data, width * height * 3, 1, file );
fclose( file );
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_DECAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_DECAL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // texture should tile
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE,data);
free(data);
return texture;
}
void FreeTexture( GLuint texture )
{
glDeleteTextures( 1, &texture );
}
void skybox (void) {
float x = 0;
float y = 0;
float z = 0;
float width = 100;
float height = 100;
float length = 100;
glPushAttrib(GL_ENABLE_BIT);
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_BLEND);
// Bind the BACK texture of the sky map to the BACK side of the cube
glBindTexture(GL_TEXTURE_2D, texture[0]);
// Center the skybox
x = x - width / 2;
y = y - height / 2;
z = z - length / 2;
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y, z);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x + width, y + height, z);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[1]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y, z + length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z + length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y, z + length);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[4]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y, z);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y, z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y, z + length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[5]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y + height, z);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y + height, z + length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[2]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z + length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y, z + length);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[3]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y, z);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y, z + length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x + width, y + height, z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z);
glEnd();
//glBindTexture( GL_TEXTURE_CUBE_MAP, texture[0] ); //bind the texture
//glRotatef( angle, 1.0f, 1.0f, 1.0f );
//glutSolidSphere(2, 40, 40);
}
void display (void) {
glClearColor (0.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLfloat light_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_position[] = { 0.0, 0.0, 30.0, 0.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLoadIdentity();
glPushMatrix();
gluLookAt (20.0, 20.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glPushMatrix();
texture[0] = LoadTexture( "back.bmp", 256, 256 ); //load the texture
texture[1] = LoadTexture( "front.bmp", 256, 256 ); //load the texture
texture[2] = LoadTexture( "left.bmp", 256, 256 ); //load the texture
texture[3] = LoadTexture( "right.bmp", 256, 256 ); //load the texture
texture[4] = LoadTexture( "bottom.bmp", 256, 256 ); //load the texture
texture[5] = LoadTexture( "top.bmp", 256, 256 ); //load the texture
glPopMatrix();
glPopMatrix();
//glEnable(GL_TEXTURE_GEN_S); //enable texture coordinate generation
//glEnable(GL_TEXTURE_GEN_T);
skybox();
for (int i = 0; i < 6; i++) {
FreeTexture( texture[i] );
}
glutSwapBuffers();
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
glOrtho(-100.0, 100.0, -100.0, 100.0,-100.0,100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main (int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("A basic OpenGL Window");
init();
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
}
So, you're trying to load DIB/BMP image files:
> texture[0] = LoadTexture( "back.bmp", 256, 256 ); //load the texture
> ^^^^
>
Reading the contents of the file
> GLuint LoadTexture( const char * filename, int width, int height) {
> GLuint texture; unsigned char * data; FILE* file;
>
> file = fopen( filename, "r" );
> if ( file == NULL ) return 0;
> data = (unsigned char *)malloc( width * height * 3 );
> fread( data, width * height * 3, 1, file );
This is too short for a BMP, BTW.
> fclose( file );
So where's your DIB parser code?
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_DECAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_DECAL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // texture should tile
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE,data);
free(data);
return texture;
}
You just pass the unparsed DIB/BMP file contents to OpenGL. What do you expect OpenGL to do with this? OpenGL has no idea about file format, less how process a DIB file. You need a DIB parser there.
Since you're loading RGB data make sure GL_UNPACK_ALIGNMENT is set to 1:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)​.
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE,data);
I use the ImageMagick open library to easily load any image for use with OpenGL.

simple 2d animation in glut

I have an assignment to do, but i can't seem to trully comprehend it.
The assignment is as follows : Adding a texture to background (solar system), adding texture to 2 objects (drawn shapes) and adding an animation where the two objects have to bounce from eachother & from far walls (as in end of screen).
I have managed to do everything except the animation.
How can I do this kind of animation?
p.s. animation in there is the best i could come up with.
#include <gl/glut.h>
#include <gl/gl.h >
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
float x;
float y;
unsigned char *imageData;
int imageRows, imageCols;
extern void loadBMP(char *);
char cotton1[] = "cotton1.bmp";
char cotton2[] = "cotton2.bmp";
char fons[] = "solar.bmp";
GLuint texture[3];
float cube[1], Vcube[1];
/* GLUT callback Handlers */
void init()
{
cube[0]=0;
Vcube[0]=0.01;
cube[1]=0;
Vcube[1]=0.01;
glShadeModel(GL_SMOOTH);
glGenTextures( 3, &texture[0] );
loadBMP(cotton1);
glBindTexture( GL_TEXTURE_2D, texture[0] );
glTexImage2D(GL_TEXTURE_2D, 0, 3, imageCols, imageRows,
0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
loadBMP(cotton2);
glBindTexture( GL_TEXTURE_2D, texture[1] );
glTexImage2D(GL_TEXTURE_2D, 0, 3, imageCols, imageRows,
0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
loadBMP(fons);
glBindTexture( GL_TEXTURE_2D, texture[2] );
glTexImage2D(GL_TEXTURE_2D, 0, 3, imageCols, imageRows,
0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
}
static void
resize(int width, int height)
{
const float ar = (float) width / (float) height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity() ;
}
static void
idle(void)
{
glutPostRedisplay();
}
void animation()
{
cube[1]+=Vcube[1];
if (cube[1]<0.1)
{ Vcube[1]+=Vcube[1]; }
if (cube[1]>0.095)
{ Vcube[1]=-0.01; }
if (cube[1]<0)
{ Vcube[1]=+0.01; }
glTranslatef(cube[1],0,0);
Sleep(100);
glutPostRedisplay();
}
void animation2()
{
cube[0]+=Vcube[0];
if (cube[0]<(-0.1))
{ Vcube[0]-=0.01; }
if (cube[0]>0)
{ Vcube[0]-=0.01; }
if (cube[0]<0.1)
{ Vcube[0]+=0.01; }
glTranslatef(cube[0],0,0);
Sleep(100);
glutPostRedisplay();
}
void display() {
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
//Background
glLoadIdentity();
glBindTexture( GL_TEXTURE_2D, texture[2]);
glEnable( GL_TEXTURE_2D );
glPushMatrix();
glBegin( GL_QUADS );
glTexCoord2f(1.0,1.0); glVertex2f(-1.0,1.0);
glTexCoord2f(0.0,1.0); glVertex2f(1.0,1.0);
glTexCoord2f(0.0,0.0); glVertex2f(1.0,-1.0);
glTexCoord2f(1.0,0.0); glVertex2f(-1.0,-1.0);
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
animation();
//TEXTURE 1
glBindTexture( GL_TEXTURE_2D, texture[0]);
glEnable( GL_TEXTURE_2D );
glPushMatrix();
glBegin( GL_TRIANGLE_FAN );
glTexCoord2f(0.5f, 0.5f); glVertex2f( 0.5f, 0.0f); //center
glTexCoord2f(1.0f, 0.5f); glVertex2f( 0.8f+x, 0.0f); //right
glTexCoord2f(0.75f, 1.0f); glVertex2f( 0.55f+x, 0.3f+x); //top right
glTexCoord2f(0.25f, 1.0f); glVertex2f( 0.35f-x, 0.3f+x); //Top left
glTexCoord2f(0.0f, 0.5f); glVertex2f( 0.25f-x, 0.0f); //left
glTexCoord2f(0.25f, 0.0f); glVertex2f( 0.45f-x,-0.3f-x); //bottom left
glTexCoord2f(0.75f, 0.0f); glVertex2f( 0.7f+x, -0.2f-x); //bottom right
glTexCoord2f(1.0f, 0.5f); glVertex2f( 0.8f+x, 0.0f); //right
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
//TEXTURE 2
animation2();
glBindTexture( GL_TEXTURE_2D, texture[1]);
glEnable( GL_TEXTURE_2D );
glPushMatrix();
glBegin( GL_TRIANGLE_FAN );
glTexCoord2f(0.5f, 0.5f); glVertex2f( -0.5f, 0.0f); //center
glTexCoord2f(1.0f, 0.5f); glVertex2f( -0.2f+y, 0.0f); //right
glTexCoord2f(0.75f, 1.0f); glVertex2f( -0.4f+y, 0.2f+y); //top right
glTexCoord2f(0.25f, 1.0f); glVertex2f( -0.7f-y, 0.1f+y); //Top left
glTexCoord2f(0.0f, 0.5f); glVertex2f( -0.8f-y, 0.0f); //left
glTexCoord2f(0.25f, 0.0f); glVertex2f( -0.7f-y, -0.1f-y); //bottom left
glTexCoord2f(0.75f, 0.0f); glVertex2f( -0.3f+y, -0.2f-y); //bottom right
glTexCoord2f(1.0f, 0.5f); glVertex2f( -0.2f+y, 0.0f); //right
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glutSwapBuffers();
glFlush();
}
static void
key(unsigned char key, int a, int b)
{
switch (key)
{
case 27 :
case 'q':
exit(0);
break;
case '+':
if ((x+0.01)<0.98)
x=x+0.01;
if ((y+0.01)<0.98)
y=y+0.01;
break;
case '-':
if ((x-0.1)>(-0.15))
x=x-0.01;
if ((y-0.1)>(-0.10))
y=y-0.01;
break;
case 'o':
if ((x+0.01)<0.98)
x=x+0.01;
break;
case 'p':
if ((x-0.1)>(-0.15))
x=x-0.01;
break;
case '[':
if ((y+0.01)<0.98)
y=y+0.01;
break;
case ']':
if ((y-0.1)>(-0.10))
y=y-0.01;
break;
}
glutPostRedisplay();
}
int main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitWindowSize(640, 640);
glutInitWindowPosition(50, 50);
glutCreateWindow("Assignment number 3");
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutReshapeFunc(resize);
glutDisplayFunc(display);
glutKeyboardFunc(key);
glutIdleFunc(idle);
glClearColor(1.0, 1.0, 1.0, 1.0);
init();
glutMainLoop();
return EXIT_SUCCESS;
}
Problem 1: You mistake OpenGL for a scene graph. Take your animation1 function for example:
void animation2(
)
{
cube[0] += Vcube[0];
if( cube[0] < ( -0.1 ) ) {
Vcube[0] -= 0.01;
}
if( cube[0] > 0 ) {
Vcube[0] -= 0.01;
}
if( cube[0] < 0.1 ) {
Vcube[0] += 0.01;
}
glTranslatef( cube[0], 0, 0 );
Sleep( 100 );
glutPostRedisplay( );
}
That glTranslatef there at the end will just trash around on whatever matrix is currently active in the OpenGL context. That's not how to do it.
Next problem: You're calling the animation functions from the drawing code. At the point of drawing all the scene state should be determined. Also, calling that animation function will sleep in your display function. That's not how to do it.
Okay, what to do: First put all the animation progressor functions into the idle loop. Don't sleep, instead measure the time between animation iterations and advance the animation accordingly. Don't call glutPostRedisplay in the animation functions. At the end of the idle handler yes, but not in the animators. In the drawing code use the evaluated animation state to place objects accordingly. Use the matrix stack (glPushMatrix, glPopMatrix) to keep things nicely separated.
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/* for gettimeofday */
#include <sys/time.h>
/* In general, littering your program with global variables should be avoided.
* I admit, that sometimes even I don't adhere to this rule, and especially
* using GLUT it takes to jump several very arcane hoops to avoid it.
* So in this case, yes, having global variables is in order.
*
* The principle idea of global variables is to put data into them, that is
* valid and the same for the whole of the program. More importantly they
* must not be used to pass around data.
*
* It's also a good idea to make those variables static, so that they are
* contained withing this compilation unit.
*/
static float x;
static float y;
/* This is not how globals should be used. They're used to pass data around between
* functions. DON'T DO THAT!
*
* Also this misses the extern keyword. Unless the compilation unit loading the
* bmp files declares those being extern, hence relying on another compilation unit
* to expose them like this, this code is likely to break.
unsigned char *imageData;
int imageRows, imageCols;
extern void loadBMP(char *);
* BTW: You don't need the extern keyword here.
* Instead have a nice little function that loads a BMP file and puts it into a
* newly allocated texture object.
*/
GLuint loadBmpToTexture(char const * const filename)
{
/* Implementation of this left as an exercise to the reader */
return 0;
}
static double ftime(void)
{
/* Now this is a bit complicated: There's no portable high resolution
* timer function. On Linux and Unices (hence also MacOS X) you have
* gettimeofday, on Windows there are the High Performance Counters.
* ... Totally annoying.
* Look here for a comparison:
* http://www.songho.ca/misc/timer/timer.html
*
* Since I'm on a Linux box this is using gettimeofday
*/
struct timeval t;
gettimeofday(&t, NULL);
return 1.0*t.tv_sec + 1e-6*t.tv_usec;
}
/* In this variable we store the time of the last iteration of the animation
* loop to determine the time to time difference for the next one. */
static double last_T;
/* Actually those should be of type char const * const
* This is one of the finer details of C. The arrays like you've declared them
* here are mutable, but of constant size.
* However you normally don't want string constant be like this. The preferred
* modus operandi is to have the string constants in read only memory and pointers
* to them. Like this:
*/
char const * const cotton1 = "cotton1.bmp";
char const * const cotton2 = "cotton2.bmp";
char const * const fons = "solar.bmp";
/* Okay, now consider what would happen if you had several objects, not just two or
* three? How would you keep track of all those indices? Really, that's bad style.
* If you've data belonging together, like state of an object, put it into a struct
* and then also use useful variable names.
*/
GLuint texture_background;
typedef struct s_Cube {
float x, V_x;
GLuint texture;
} Cube;
/* also we can statically initialize here */
Cube cube[2] = {
{-0.05, 0.01, 0},
{0.05, -0.02, 0}
};
/* GLUT callback Handlers */
static void init(void)
{
/* loadBmpToTexture is defined to return 0 in case of failure
* which is also the OpenGL default texture object, so this
* fails safely. */
texture_background = loadBmpToTexture(fons);
cube[0].texture = loadBmpToTexture(cotton1);
cube[1].texture = loadBmpToTexture(cotton2);
glClearColor( 0.0, 0.5, 0.7, 1.0 );
last_T = ftime();
}
static void animation(
float const speed
)
{
/* The objective is to let the cubes bounce into each other
* (collision) and with the walls. First the collision: */
if( cube[0].x > cube[1].x && cube[0].V_x > 0 && cube[1].V_x < 0 ) {
/* cubes bounced off each other. Exchange their velocities */
double const V_x = cube[0].V_x;
cube[0].V_x = cube[1].V_x;
cube[1].V_x = V_x;
double const x = cube[0].x;
cube[0].x = cube[1].x;
cube[1].x = x;
}
/* and the wall bounce */
if( cube[0].x < -0.1 && cube[0].V_x < 0 ) {
/* left cube bounced into left wall */
cube[0].V_x *= -1;
}
if( cube[1].x > 0.1 && cube[1].V_x > 0 ) {
/* right cube bounced into left wall */
cube[1].V_x *= -1;
}
cube[0].x += speed * cube[0].V_x;
cube[1].x += speed * cube[1].V_x;
}
/* Ideally we'd use a precise animation loop interleaved with event processing here.
* Unfortunately GLUT doesn't offer those, so we use this arcane kludge.
*
* It would get a bit more robust by putting the whole timing into the display function
* but better abandon GLUT and get a true event loop.
*/
static void idle(
void )
{
const double now_T = ftime();
const double delta_T = now_T - last_T;
last_T = now_T;
const double speed = delta_T * 60;
animation( speed );
glutPostRedisplay( );
}
static void display(void)
{
/* We try to be as stateless as possible. Yes, in the face of a statefull
* API, like OpenGL, this may sound a bit pedantic. */
const int width = glutGet(GLUT_WINDOW_WIDTH);
const int height = glutGet(GLUT_WINDOW_HEIGHT);
const float ar = ( float ) width / ( float ) height;
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
/* It's really best practice to set everything related to drawing
* – and that includes the projection – in the drawing function */
glViewport( 0, 0, width, height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho(-ar, ar, -1, 1, -1, 1);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
//Background
if(texture_background) {
glBindTexture( GL_TEXTURE_2D, texture_background );
glEnable( GL_TEXTURE_2D );
glBegin( GL_QUADS );
glTexCoord2f( 1.0, 1.0 );
glVertex2f( -1.0, 1.0 );
glTexCoord2f( 0.0, 1.0 );
glVertex2f( 1.0, 1.0 );
glTexCoord2f( 0.0, 0.0 );
glVertex2f( 1.0, -1.0 );
glTexCoord2f( 1.0, 0.0 );
glVertex2f( -1.0, -1.0 );
glEnd();
glDisable( GL_TEXTURE_2D );
}
//TEXTURE 1
glBindTexture( GL_TEXTURE_2D, cube[1].texture );
glEnable( GL_TEXTURE_2D );
/* Remember we're still in modelview matrix mode.
* This push creates a copy of the currently modelview matrix,
* for our disposal. With a following pop we restore to the
* state saved now. Pushes and Pops nest. */
glPushMatrix();
/* This applies our animation position to the modelview matrix.
* All geometry drawing to follow is subject to this additional
* transformation, until the matrix changes again. */
glTranslatef(cube[1].x, 0, 0);
glBegin( GL_TRIANGLE_FAN );
glTexCoord2f( 0.5f, 0.5f );
glVertex2f( 0.5f, 0.0f ); //center
glTexCoord2f( 1.0f, 0.5f );
glVertex2f( 0.8f + x, 0.0f ); //right
glTexCoord2f( 0.75f, 1.0f );
glVertex2f( 0.55f + x, 0.3f + x ); //top right
glTexCoord2f( 0.25f, 1.0f );
glVertex2f( 0.35f - x, 0.3f + x ); //Top left
glTexCoord2f( 0.0f, 0.5f );
glVertex2f( 0.25f - x, 0.0f ); //left
glTexCoord2f( 0.25f, 0.0f );
glVertex2f( 0.45f - x, -0.3f - x ); //bottom left
glTexCoord2f( 0.75f, 0.0f );
glVertex2f( 0.7f + x, -0.2f - x ); //bottom right
glTexCoord2f( 1.0f, 0.5f );
glVertex2f( 0.8f + x, 0.0f ); //right
glEnd( );
glPopMatrix( );
glDisable( GL_TEXTURE_2D );
//TEXTURE 2
/* in the original code you didn't use the other texture,
* Probably because you lost track of variables and indices. */
glBindTexture( GL_TEXTURE_2D, cube[0].texture );
glEnable( GL_TEXTURE_2D );
glPushMatrix();
glTranslatef(cube[0].x, 0, 0);
glBegin( GL_TRIANGLE_FAN );
glTexCoord2f( 0.5f, 0.5f );
glVertex2f( -0.5f, 0.0f ); //center
glTexCoord2f( 1.0f, 0.5f );
glVertex2f( -0.2f + y, 0.0f ); //right
glTexCoord2f( 0.75f, 1.0f );
glVertex2f( -0.4f + y, 0.2f + y ); //top right
glTexCoord2f( 0.25f, 1.0f );
glVertex2f( -0.7f - y, 0.1f + y ); //Top left
glTexCoord2f( 0.0f, 0.5f );
glVertex2f( -0.8f - y, 0.0f ); //left
glTexCoord2f( 0.25f, 0.0f );
glVertex2f( -0.7f - y, -0.1f - y ); //bottom left
glTexCoord2f( 0.75f, 0.0f );
glVertex2f( -0.3f + y, -0.2f - y ); //bottom right
glTexCoord2f( 1.0f, 0.5f );
glVertex2f( -0.2f + y, 0.0f ); //right
glEnd();
glPopMatrix();
glDisable( GL_TEXTURE_2D );
glutSwapBuffers();
/* Your glFinish here was totally pointless.
* First it would belong _before_ glutSwapBuffers.
* Second glutSwapBuffers implies a glFinish, so it's totally redundant. */
}
static void key(
unsigned char key,
int a,
int b )
{
switch ( key ) {
case 27:
case 'q':
exit( 0 );
break;
case '+':
if( ( x + 0.01 ) < 0.98 )
x = x + 0.01;
if( ( y + 0.01 ) < 0.98 )
y = y + 0.01;
break;
case '-':
if( ( x - 0.1 ) > ( -0.15 ) )
x = x - 0.01;
if( ( y - 0.1 ) > ( -0.10 ) )
y = y - 0.01;
break;
case 'o':
if( ( x + 0.01 ) < 0.98 )
x = x + 0.01;
break;
case 'p':
if( ( x - 0.1 ) > ( -0.15 ) )
x = x - 0.01;
break;
case '[':
if( ( y + 0.01 ) < 0.98 )
y = y + 0.01;
break;
case ']':
if( ( y - 0.1 ) > ( -0.10 ) )
y = y - 0.01;
break;
}
glutPostRedisplay();
}
int main(
int argc,
char *argv[] )
{
glutInit( &argc, argv );
glutInitWindowSize( 640, 640 );
glutInitWindowPosition( 50, 50 );
/* glutInitDisplayMode must be called before calling glutCreateWindow
* GLUT, like OpenGL is stateful */
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH );
glutCreateWindow( "Assignment number 3" );
glutDisplayFunc( display );
glutKeyboardFunc( key );
glutIdleFunc( idle );
init();
glutMainLoop( );
return EXIT_SUCCESS;
}