OpenGL glutSwapBuffers does not draw the scene - linux

So this is really odd, I'm on ubuntu and when I try running this sample program I can't get the window to show up properly. If I switch it to glFlush and to use GLUT_SINGLE instead of GLUT_DOUBLE then it works perfectly fine. Any reason why this is happening?
#include <iostream>
#include <GL/glut.h>
using namespace std;
// Initialization routine.
void setup(void)
{
glEnableClientState(GL_VERTEX_ARRAY);
glClearColor(1.0, 1.0, 1.0, 0.0);
}
// Drawing routine.
void drawScene(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(1.0, 1.0, 1.0, 0.0);
glLoadIdentity();
gluLookAt(0,0,0,0,0,0,0,1,0);
glColor3f(1,0,1);
glutSolidCube(1);
glutSwapBuffers();
//glFlush();
}
// OpenGL window reshape routine.
void resize(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90.0, (float)w/(float)h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}
// Main routine.
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
//glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("Test");
setup();
glutDisplayFunc(drawScene);
glutReshapeFunc(resize);
glutMainLoop();
return 0;
}

Don't tempt fate, reset your matrices every time through your display callback:
#include <GL/glut.h>
void drawScene()
{
glClearColor(1.0, 1.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
gluPerspective(60, w / h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1,1,1,0,0,0,0,1,0);
glColor3f(1,0,1);
glutSolidCube(1);
glutSwapBuffers();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("Test");
glutDisplayFunc(drawScene);
glutMainLoop();
return 0;
}
Also, setting the eye and center points in gluLookAt() to the same position is Bad (see the calculation of the F and f vectors).

Related

After XResizeWindow, new window content drawn is not displayed

I'm writing an application in Linux using Xlib to manage a window and cairo to draw some text in it. The text content of the window changes during the execution, so I want to adapt the window size to match that of the text extent. If the size of the text extent does not change, the window is always correctly updated with the new text.
But when the text extent changes, and so the window is resized accordingly, the window is cleared but the new text is never shown. Only if there is no call to XResizeWindow the text is actually displayed. The code I'm using is
if (/* Text extent is changed */)
{
XResizeWindow (display, window, new_width, new_height);
cairo_xlib_surface_set_size (surface, new_width, new_height);
}
XClearWindow (display, window);
/* ... Cairo code to draw the text ... */
// cairo_surface_flush (surface);
// XFlush (display);
I have also tried to add after the Cairo code that draws the text the methods cairo_surface_flush and XFlush (commented in the example) but nothing changes.
EDIT: I solved the problem using two threads: the first thread with the usual loop for listening to the Expose events plus the code to redraw the content and the second thread that issues the resize of the window and sends an Expose event to wake up the first thread.
In this example the window is resized every 500 ms to random width and height and a progressive counter is displayed in it at every resize. I use C++11, compile with:
g++ -std=c++11 -o test test.cpp -lX11 -lcairo -lpthread
The code is:
#include <random>
#include <chrono>
#include <thread>
#include <string>
#include <X11/Xlib.h>
#include <cairo/cairo-xlib.h>
Display * d;
Window w;
cairo_surface_t * surface;
int width = 300, height = 300;
unsigned char counter = 0;
std::random_device rd;
std::knuth_b gen (rd ());
std::uniform_int_distribution < > dist (150, 300);
void logic ()
{
XEvent send_event;
send_event.type = Expose;
send_event.xexpose.window = w;
while (true)
{
std::this_thread::sleep_for (std::chrono::milliseconds (500));
++ counter;
width = dist (gen);
height = dist (gen);
cairo_xlib_surface_set_size (surface, width, height);
XResizeWindow (d, w, width, height);
XSendEvent (d, w, False, ExposureMask, & send_event);
XFlush (d);
}
}
int main ( )
{
XInitThreads ();
d = XOpenDisplay (NULL);
w = XCreateSimpleWindow (d, RootWindow (d, 0), 0, 0, width, height, 0, 0, 0x000000);
XMapWindow (d, w);
XSelectInput (d, w, ExposureMask | KeyPressMask);
surface = cairo_xlib_surface_create (d, w, DefaultVisual (d, 0), width, height);
cairo_t * cairo = cairo_create (surface);
cairo_select_font_face (cairo, "FreeSans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size (cairo, 40 );
cairo_set_source_rgb (cairo, 0.8, 0.8, 0.8);
cairo_move_to (cairo, 40.0, 60.0);
cairo_show_text (cairo, std::to_string (counter).c_str ());
XFlush (d);
std::thread T (logic);
XEvent event;
while (true)
{
XNextEvent (d, & event);
if (event.type == Expose)
{
XClearWindow (d, w);
cairo_move_to (cairo, 40.0, 60.0);
cairo_show_text (cairo, std::to_string (counter).c_str ());
}
else if (event.type == KeyPress)
{
XCloseDisplay (d);
return 0;
}
}
}
But a question remains: is it possible to obtain the same result using only one thread?
Here is a single-threaded version of your code. It is not nice, but it seems to work. The hard part is waiting for events from the X11 server and the timeout simultaneously. I do this with select() in the following code.
Note that I also handle ConfigureNotify events instead of assuming that XResizeWindow always does just what we want.
#include <random>
#include <chrono>
#include <thread>
#include <string>
#include <X11/Xlib.h>
#include <cairo/cairo-xlib.h>
#include <sys/time.h>
Display * d;
Window w;
cairo_surface_t * surface;
int width = 300, height = 300;
unsigned char counter = 0;
std::random_device rd;
std::knuth_b gen (rd ());
std::uniform_int_distribution < > dist (150, 300);
void do_update ()
{
++ counter;
width = dist (gen);
height = dist (gen);
XResizeWindow (d, w, width, height);
// Force a redraw
XClearArea(d, w, 0, 0, 0, 0, True);
}
int main ( )
{
XInitThreads ();
d = XOpenDisplay (NULL);
w = XCreateSimpleWindow (d, RootWindow (d, 0), 0, 0, width, height, 0, 0, 0x000000);
XMapWindow (d, w);
XSelectInput (d, w, ExposureMask | KeyPressMask);
surface = cairo_xlib_surface_create (d, w, DefaultVisual (d, 0), width, height);
cairo_t * cairo = cairo_create (surface);
cairo_select_font_face (cairo, "FreeSans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size (cairo, 40 );
cairo_set_source_rgb (cairo, 0.8, 0.8, 0.8);
cairo_move_to (cairo, 40.0, 60.0);
cairo_show_text (cairo, std::to_string (counter).c_str ());
XFlush (d);
struct timeval next_update;
struct timeval now;
struct timeval interval = { 0, 500000 };
gettimeofday(&now, NULL);
timeradd(&now, &interval, &next_update);
while (true)
{
XEvent event;
gettimeofday(&now, NULL);
if (timercmp(&now, &next_update, >)) {
// Store time of next update
timeradd(&now, &interval, &next_update);
puts("update");
do_update();
}
if (!XPending(d)) {
struct timeval remaining;
fd_set fds;
int fd = ConnectionNumber(d);
FD_ZERO(&fds);
FD_SET(fd, &fds);
timersub(&next_update, &now, &remaining);
select(fd + 1, &fds, NULL, NULL, &remaining);
} else {
XNextEvent (d, & event);
if (event.type == Expose)
{
XClearWindow (d, w);
cairo_move_to (cairo, 40.0, 60.0);
cairo_show_text (cairo, std::to_string (counter).c_str ());
}
if (event.type == ConfigureNotify)
{
cairo_xlib_surface_set_size (surface, event.xconfigure.width, event.xconfigure.height);
}
else if (event.type == KeyPress)
{
XCloseDisplay (d);
return 0;
}
}
}
}

Display RGB window in linux using OpenGL and Freeglut

I want to create a window covering my whole desktop screen with displaying colors RGB and then VIBGYOR. The color delay should be 1 second.
This is the code I have written but output is not as expected. Can anyone tell me where I am wrong?
#include<GL/freeglut.h>
#include<GL/glut.h>
#include<stdio.h>
void main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
glutInitWindowSize(1280,1024);
glutCreateWindow("Displays");
glutFullScreen();
glClearColor (1.0, 0.0, 0.0, 0.0); //Red
glClear(GL_COLOR_BUFFER_BIT);
sleep(1);
glClearColor(0,1,0,0); //Green
glClear(GL_COLOR_BUFFER_BIT);
sleep(1);
glClearColor(0,0,1,0);
glClear(GL_COLOR_BUFFER_BIT); //Blue
sleep(1);
glClearColor(0.933, 0.510, 0.933, 0.0); //violet
glClear(GL_COLOR_BUFFER_BIT);
sleep(1);
glClearColor(0.294, 0.000, 0.510, 1); //Indigo
glClear(GL_COLOR_BUFFER_BIT);
sleep(1);
glClearColor(0,0,1,1); //Blue
glClear(GL_COLOR_BUFFER_BIT);
sleep(1);
glClearColor(0,0.502,0,1); //Green
glClear(GL_COLOR_BUFFER_BIT);
sleep(1);
glClearColor(1,1,0,1); //Yellow
glClear(GL_COLOR_BUFFER_BIT);
sleep(1);
glClearColor(1,0.647,0,1); //Orange
glClear(GL_COLOR_BUFFER_BIT);
sleep(1);
glClearColor(1,0,0,1); //Red
glClear(GL_COLOR_BUFFER_BIT);
sleep(1);
glutMainLoop();
}
Thanks.
You're initializing the display mode with GLUT_DOUBLE (double buffering), you need to add gluSwapBuffers() every time you're finished working with the buffer and want to display it.
...
glClearColor(1,0,0,1); //Red
glClear(GL_COLOR_BUFFER_BIT);
glutSwapBuffers();
sleep(1);
...
Difference between single buffered(GLUT_SINGLE) and double buffered drawing(GLUT_DOUBLE)
When using GL_SINGLE, you can picture your code drawing directly to the display.
When using GL_DOUBLE, you can picture having two buffers. One of them is always visible, the other one is not
glut examples
nehe's legacy tutorials
What is the nicest way to close GLUT
void glutLeaveMainLoop ( void );

why the opengl can't print string

#include "stdafx.h"
#include <gl/glut.h>
void resizeEvent(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, w, h, 0);
glMatrixMode(GL_MODELVIEW);
glutPostRedisplay();
}
void displayEvent()
{
glClearColor(1, 1, 1, 0);
glClear(GL_COLOR_BUFFER_BIT);
glutSwapBuffers();
char text[] = "Hello World!";
glRasterPos2d(110, 110);
glColor3f(1, 0, 0);
for(int i=0; text[i] != '\0'; i++)
{
glutBitmapCharacter(GLUT_BITMAP_8_BY_13, text[i]);
}
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 300);
glutInitWindowPosition(0, 0);
glutCreateWindow("Hello");
glutDisplayFunc(displayEvent);
glutReshapeFunc(resizeEvent);
glutMainLoop();
return 0;
}
I learn from a ppt,and think it will print a string.But it does not work .I search from google,but no answer. I don't know why it can't print a string.
if glutBitmapCharacter is wrong ?
All the commands in opengl, renders on the frame buffer only when flush or finish call happens, so all your commands are still in queue and yet to be displayed on frame buffer. You need to call glFlush/glFinish at the end, glut provides glutSwapBuffers, so in the end of your displayEvent function you need to call glutSwapBuffers to see the effect of your displayEvent function.

OpenGL double buffers on Ubuntu does not work

I'm testing out several of Sumantha Guha's code and there's something that isn't working quite right... All of the sample code where he uses GLUT_DOUBLE and glutSwapBuffers() does not work on my ubuntu machine, but works on my Windows machine. More accurately the window that pops out simply traces the background.
I've had this issue before on Windows where Flush and single buffers don't work, but now this is happening on Linux where Double buffers and glutSwapBuffers do not work. Any idea as to what may be causing this?
Sample of code that I tried loading. Compiles fine, just get a window that traces the background.
///////////////////////////////////////////////////////////////////////////////////////////////////////
// loadTextures.cpp
//
// This stripped-down program shows how to load both external and program-generated images as textures.
//
// NOTE: The Textures folder must be in the same one as this program.
//
// Interaction:
// Press the left and right arrow keys to rotate the square.
// Press space to toggle between textures.
// Press delete to reset.
//
// Sumanta Guha
///////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////
// TEXTURE GREDITS:
// canLabel.bmp, thanks anonymous.
// canTop.bmp, thanks www.acoustica.com.
// cray2.bmp, thanks NASA website www.nasa.gov.
// grass.bmp, thanks www.amazingtextures.com.
// launch.bmp, thanks NASA website www.nasa.gov.
// nightsky.bmp, thanks anonymous.
// sky.bmp, thanks www.mega-tex.nl.
// trees.bmp, thanks anonymous.
////////////////////////////////////////////////
#include <cstdlib>
#include <iostream>
#include <fstream>
#ifdef __APPLE__
# include <GLUT/glut.h>
# include <OpenGL/glext.h>
#else
# include <GL/glut.h>
# include <GL/glext.h>
#endif
using namespace std;
// Globals.
static unsigned int texture[2]; // Array of texture indices.
static unsigned char chessboard[64][64][3]; // Storage for chessboard image.
static float angle = 0.0; // Angle to rotate textured square.
static int id = 0; // Currently displayed texture id.
// Struct of bitmap file.
struct BitMapFile
{
int sizeX;
int sizeY;
unsigned char *data;
};
// Routine to read a bitmap file.
// Works only for uncompressed bmp files of 24-bit color.
BitMapFile *getBMPData(string filename)
{
BitMapFile *bmp = new BitMapFile;
unsigned int size, offset, headerSize;
// Read input file name.
ifstream infile(filename.c_str(), ios::binary);
// Get the starting point of the image data.
infile.seekg(10);
infile.read((char *) &offset, 4);
// Get the header size of the bitmap.
infile.read((char *) &headerSize,4);
// Get width and height values in the bitmap header.
infile.seekg(18);
infile.read( (char *) &bmp->sizeX, 4);
infile.read( (char *) &bmp->sizeY, 4);
// Allocate buffer for the image.
size = bmp->sizeX * bmp->sizeY * 24;
bmp->data = new unsigned char[size];
// Read bitmap data.
infile.seekg(offset);
infile.read((char *) bmp->data , size);
// Reverse color from bgr to rgb.
int temp;
for (int i = 0; i < size; i += 3)
{
temp = bmp->data[i];
bmp->data[i] = bmp->data[i+2];
bmp->data[i+2] = temp;
}
return bmp;
}
// Load external textures.
void loadExternalTextures()
{
// Local storage for bmp image data.
BitMapFile *image[1];
// Load the texture.
image[0] = getBMPData("Textures/launch.bmp");
// Activate texture index texture[0].
glBindTexture(GL_TEXTURE_2D, texture[0]);
// Set texture parameters for wrapping.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture parameters for filtering.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Specify an image as the texture to be bound with the currently active texture index.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image[0]->sizeX, image[0]->sizeY, 0,
GL_RGB, GL_UNSIGNED_BYTE, image[0]->data);
}
// Routine to load a program-generated image as a texture.
void loadProceduralTextures()
{
// Activate texture index texture[1].
glBindTexture(GL_TEXTURE_2D, texture[1]);
// Set texture parameters for wrapping.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture parameters for filtering.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// Specify an image as the texture to be bound with the currently active texture index.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, chessboard);
}
// Create 64 x 64 RGB image of a chessboard.
void createChessboard(void)
{
int i, j;
for (i = 0; i < 64; i++)
for (j = 0; j < 64; j++)
if ( ( ((i/8)%2) && ((j/8)%2) ) || ( !((i/8)%2) && !((j/8)%2) ) )
{
chessboard[i][j][0] = 0x00;
chessboard[i][j][1] = 0x00;
chessboard[i][j][2] = 0x00;
}
else
{
chessboard[i][j][0] = 0xFF;
chessboard[i][j][1] = 0xFF;
chessboard[i][j][2] = 0xFF;
}
}
// Initialization routine.
void setup(void)
{
glClearColor(0.8, 0.8, 0.8, 0.0);
// Create texture index array.
glGenTextures(2, texture);
// Load external texture and generate and load procedural texture.
loadExternalTextures();
createChessboard();
loadProceduralTextures();
// Turn on OpenGL texturing.
glEnable(GL_TEXTURE_2D);
// Specify how texture values combine with current surface color values.
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
// Drawing routine.
void drawScene(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glRotatef(angle, 0.0, 1.0, 0.0);
// Activate a texture.
glBindTexture(GL_TEXTURE_2D, texture[id]);
// Map the texture onto a square polygon.
glBegin(GL_POLYGON);
glTexCoord2f(0.0, 0.0); glVertex3f(-10.0, -10.0, 0.0);
glTexCoord2f(1.0, 0.0); glVertex3f(10.0, -10.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(10.0, 10.0, 0.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-10.0, 10.0, 0.0);
glEnd();
glutSwapBuffers();
}
// OpenGL window reshape routine.
void resize(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-5.0, 5.0, -5.0, 5.0, 5.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// Keyboard input processing routine.
void keyInput(unsigned char key, int x, int y)
{
switch(key)
{
case 27:
exit(0);
break;
case ' ':
id++;
if (id == 2) id = 0;
glutPostRedisplay();
break;
case 127:
angle = 0.0;
glutPostRedisplay();
break;
default:
break;
}
}
// Callback routine for non-ASCII key entry.
void specialKeyInput(int key, int x, int y)
{
if (key == GLUT_KEY_LEFT)
{
angle -= 5.0;
if (angle < 0.0) angle += 360.0;
}
if (key == GLUT_KEY_RIGHT)
{
angle += 5.0;
if (angle > 360.0) angle -= 360.0;
}
glutPostRedisplay();
}
// Routine to output interaction instructions to the C++ window.
void printInteraction(void)
{
cout << "Interaction:" << endl;
cout << "Press the left and right arrow keys to rotate the square." << endl
<< "Press space to toggle between textures." << endl
<< "Press delete to reset." << endl;
}
// Main routine.
int main(int argc, char **argv)
{
printInteraction();
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("loadTextures.cpp");
setup();
glutDisplayFunc(drawScene);
glutReshapeFunc(resize);
glutKeyboardFunc(keyInput);
glutSpecialFunc(specialKeyInput);
glutMainLoop();
return 0;
}

OpenGL sample particle simulation doesnt show up particles

I have created a simple particle simulation for a fountain from this source. I also wanted to implement this using C++ classes. So, tried to put the above part of the logic into classes at this source (This is a very nice framework). I just have to inherit the class and redefine the functionalities that I would like.
I defined the functions for display() in which I call my DrawObjects().
I am running into the following issues:
I am initializing the number of particles to as low as 50 or 100 or 500. Nothing visible.
I am trying to load a texture(BMP) for my particles. It is failing for some reason. I tried both relative and absolute paths. Then tried to load a RAW texture(using IrfanViewer) with no luck. Also tried to remove the texture code to make them simple OpenGL primitives. Again no luck.
I wrote a simple DrawAxis() function which actually needs to draw cyan colored axis with red colored strings. However, gray colored primitives are showing up. I checked the code for usage of grayscale configuration, but no such thing.
Note: Working on Windows VC++ 2010. Code can be found at NippyZip.
Minimal Code
Main.cpp
#include "ParticleSimulation.h"
int main(int argc, char *argv[]) {
ParticleSimulation particleSimulation(50);
particleSimulation.InitParticles();
particleSimulation.setLookAt(80.0, 80.0, 80.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
particleSimulation.startFramework(argc, argv);
// **Note** No code below startFramework() will get executed
return 0;
}
GlutFramework.cpp
#include "GlutFramework.h"
namespace glutFramework {
// Set constants
const double GlutFramework::FRAME_TIME = 1.0 / GlutFramework::FPS * 1000.0; // Milliseconds
GlutFramework *GlutFramework::instance = NULL;
GlutFramework::GlutFramework() {
elapsedTimeInSeconds = 0;
frameTimeElapsed = 0;
title = "GLUT Framework: Paul Solt 2010";
eyeVector = Vector<float>(0.0, 0.0, -10.0); // move the eye position back
position = 0.0f;
direction = 1.0 / FRAME_TIME;
}
GlutFramework::~GlutFramework() {
}
void GlutFramework::startFramework(int argc, char *argv[]) {
setInstance(); // Sets the instance to self, used in the callback wrapper functions
// Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(WINDOW_X_POSITION, WINDOW_Y_POSITION);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutCreateWindow(title.c_str());
// Function callbacks with wrapper functions
glutReshapeFunc(reshapeWrapper);
glutMouseFunc(mouseButtonPressWrapper);
glutMotionFunc(mouseMoveWrapper);
glutDisplayFunc(displayWrapper);
glutKeyboardFunc(keyboardDownWrapper);
glutKeyboardUpFunc(keyboardUpWrapper);
glutSpecialFunc(specialKeyboardDownWrapper);
glutSpecialUpFunc(specialKeyboardUpWrapper);
init(); // Initialize
glutIdleFunc(runWrapper); // The program run loop
glutMainLoop(); // Start the main GLUT thread
}
void GlutFramework::load() {
// Subclass and override this method
}
void GlutFramework::display(float dTime) {
// Subclass and override this method
static int frame = 0;
std::cout << "GlutFramework Display: Frame: " << frame << ", dt(sec): " << dTime << ", Position: " << position << std::endl;
++frame;
// DEMO: Create a teapot and move it back and forth on the x-axis
glTranslatef(position, 0.0f, 0.0f);
glutSolidTeapot(2.5);
if(position > 4 && direction > 0) {
direction = -1.0 / FRAME_TIME;
} else if(position < -4 && direction < 0) {
direction = 1.0 / FRAME_TIME;
}
position += direction;
}
void GlutFramework::reshape(int width, int height) {
glViewport(0,0,(GLsizei)width,(GLsizei)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, (GLdouble) width, 0.0, (GLdouble) height);
}
void GlutFramework::mouseButtonPress(int button, int state, int x, int y) {
printf("MouseButtonPress: x: %d y: %d\n", x, y);
}
void GlutFramework::mouseMove(int x, int y) {
printf("MouseMove: x: %d y: %d\n", x, y);
}
void GlutFramework::keyboardDown( unsigned char key, int x, int y )
{
// Subclass and override this method
printf( "KeyboardDown: %c = %d\n", key, (int)key );
if (key==27) { //27 =- ESC key
exit (0);
}
keyStates.keyDown( (int)key );
}
void GlutFramework::keyboardUp( unsigned char key, int x, int y )
{
// Subclass and override this method
printf( "KeyboardUp: %c \n", key );
keyStates.keyUp( (int)key );
}
void GlutFramework::specialKeyboardDown( int key, int x, int y )
{
// Subclass and override this method
printf( "SpecialKeyboardDown: %d\n", key );
}
void GlutFramework::specialKeyboardUp( int key, int x, int y )
{
// Subclass and override this method
printf( "SpecialKeyboardUp: %d \n", key );
}
// ******************************
// ** Graphics helper routines **
// ******************************
// Initialize the projection/view matricies.
void GlutFramework::setDisplayMatricies() {
/* Setup the projection and model view matricies */
int width = glutGet( GLUT_WINDOW_WIDTH );
int height = glutGet( GLUT_WINDOW_HEIGHT );
float aspectRatio = width/height;
glViewport( 0, 0, width, height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 60, aspectRatio, 1, 500.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt(eyeVector.x, eyeVector.y, eyeVector.z,
centerVector.x, centerVector.y, centerVector.z,
upVector.x, upVector.y, upVector.z);
}
void GlutFramework::setupLights() {
GLfloat light1_position[] = { 0.0, 1.0, 1.0, 0.0 };
GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
GLfloat ambient_light[] = { 0.8, 0.8, 0.8, 1.0 };
glLightfv( GL_LIGHT0, GL_POSITION, light1_position );
glLightfv( GL_LIGHT0, GL_AMBIENT, ambient_light );
glLightfv( GL_LIGHT0, GL_DIFFUSE, white_light );
glLightfv( GL_LIGHT0, GL_SPECULAR, white_light );
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lmodel_ambient );
}
void GlutFramework::setLookAt(float eyeX, float eyeY, float eyeZ,
float centerX, float centerY, float centerZ, float upX, float upY, float upZ) {
eyeVector = Vector<float>(eyeX, eyeY, eyeZ);
centerVector = Vector<float>(centerX, centerY, centerZ);
upVector = Vector<float>(upX, upY, upZ);
}
Vector<float> GlutFramework::getEyeVector() const {
return eyeVector;
}
Vector<float> GlutFramework::getCenterVector() const {
return centerVector;
}
Vector<float> GlutFramework::getUpVector() const {
return upVector;
}
void GlutFramework::setTitle(std::string theTitle) {
title = theTitle;
}
// **************************
// ** GLUT Setup functions **
// **************************
void GlutFramework::init() {
glClearColor(0.0, 0.0, 0.0, 1.0);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
load();
}
void GlutFramework::setInstance() {
//std::cout << "GlutFramework::setInstance()" << std::endl;
instance = this;
}
void GlutFramework::run() {
if(frameRateTimer.isStopped()) { // The initial frame has the timer stopped, start it once
frameRateTimer.start();
}
frameRateTimer.stop(); // stop the timer and calculate time since last frame
double milliseconds = frameRateTimer.getElapsedMilliseconds();
frameTimeElapsed += milliseconds;
if( frameTimeElapsed >= FRAME_TIME ) { // If the time exceeds a certain "frame rate" then show the next frame
glutPostRedisplay();
frameTimeElapsed -= FRAME_TIME; // remove a "frame" and start counting up again
}
frameRateTimer.start(); // start the timer
}
void GlutFramework::displayFramework() {
if(displayTimer.isStopped()) { // Start the timer on the initial frame
displayTimer.start();
}
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // Clear once
displayTimer.stop(); // Stop the timer and get the elapsed time in seconds
elapsedTimeInSeconds = displayTimer.getElapsedSeconds(); // seconds
setupLights();
setDisplayMatricies();
display(elapsedTimeInSeconds);
glutSwapBuffers();
displayTimer.start(); // reset the timer to calculate the time for the next frame
}
// ******************************************************************
// ** Static functions which are passed to Glut function callbacks **
// ******************************************************************
void GlutFramework::displayWrapper() {
instance->displayFramework();
}
void GlutFramework::reshapeWrapper(int width, int height) {
instance->reshape(width, height);
}
void GlutFramework::runWrapper() {
instance->run();
}
void GlutFramework::mouseButtonPressWrapper(int button, int state, int x, int y) {
instance->mouseButtonPress(button, state, x, y);
}
void GlutFramework::mouseMoveWrapper(int x, int y) {
instance->mouseMove(x, y);
}
void GlutFramework::keyboardDownWrapper(unsigned char key, int x, int y) {
instance->keyboardDown(key,x,y);
}
void GlutFramework::keyboardUpWrapper(unsigned char key, int x, int y) {
instance->keyboardUp(key,x,y);
}
void GlutFramework::specialKeyboardDownWrapper(int key, int x, int y) {
instance->specialKeyboardDown(key,x,y);
}
void GlutFramework::specialKeyboardUpWrapper(int key, int x, int y) {
instance->specialKeyboardUp(key,x,y);
}
} // namespace
ParticleSimulation.h
#include "preheader.h"
#include "Particle.h"
#include "GlutFramework.h"
#ifndef ___PARTICLESIMULATION_H___
#define ___PARTICLESIMULATION_H___
using namespace glutFramework;
#ifndef ABS_IMAGE_LOCATION
#define ABS_IMAGE_LOCATION "E:/IIIT B/College/Sem 3/CG/GraphicAssignment3/images/particle.bmp"
#endif
class ParticleSimulation : virtual public GlutFramework{
private:
GLuint numParticles; // total number of particles in the system
Particle *particles;
GLuint textureParticle;
//static GLint textureCount;
//functions
void AllocateObjects(void );
void DeAllocateObjects(void );
public:
ParticleSimulation(void );
ParticleSimulation(GLuint numParticles);
~ParticleSimulation(void );
void InitParticles(void );
void EvolveParticle(void );
void DisplayObjects(void );
void LoadTextureRAW(const char * filename, int wrap);
void LoadTextureBMP(const char * filename, int wrap);
void FreeTexture(void );
void DrawAxis();
void RenderBitmapString(GLfloat x, GLfloat y, GLfloat z, void *font, char *string);
//virtual functions
void display(float dTime);
};
#endif //___PARTICLESIMULATION_H___
ParticleSimulation.cpp
#include "ParticleSimulation.h"
using namespace std;
. . .
void ParticleSimulation::DisplayObjects(){
// rendering functions
glLoadIdentity();
//glRotatef(20.0, 1.0, 0.0, 0.0); // show scene from top front
//glBindTexture(GL_TEXTURE_2D, this->textureParticle); // choose particle texture
for (int i = 0; i <= this->numParticles; i++){
GLfloat xpos = 0.0f, ypos = 0.0f, zpos = 0.0f;
particles[i].getPosition(xpos, ypos, zpos);
if(ypos < 0.0)
particles[i].setLifeTime(0.0);
if(particles[i].getActiveStatus() && particles[i].getLifeTime() > 0.0) {
GLfloat red = 0.0f, green = 0.0f, blue = 0.0f;
particles[i].getColor(red, green, blue);
glColor3f(red, green, blue);
glBegin(GL_TRIANGLE_STRIP);
glVertex2f(0.0,1.0); glVertex3f(xpos + 0.002, ypos + 0.002, zpos + 0.0); // top right
glVertex2f(0.0,0.0); glVertex3f(xpos - 0.002, ypos + 0.002, zpos + 0.0); // top left
glVertex2f(1.0,1.0); glVertex3f(xpos + 0.002, ypos - 0.002, zpos + 0.0); // bottom right
glVertex2f(1.0,0.0); glVertex3f(xpos - 0.002, ypos - 0.002, zpos + 0.0); // bottom left
//glTexCoord2f(1.0,0.0); glVertex3f(xpos - 0.002, ypos - 0.002, zpos + 0.0); // bottom left
glEnd();
} else {
particles[i].CreateParticle();
}
}
EvolveParticle();
}
void ParticleSimulation::EvolveParticle()
{
for(int i = 0; i <= this->numParticles; i++){ // evolve the particle parameters
GLfloat xpos = 0.0f, ypos = 0.0f, zpos = 0.0f;
GLfloat green = 0.0f, red = 0.0f, blue = 0.0f;
GLfloat xVel = 0.0f, yVel = 0.0f, zVel = 0.0f;
particles[i].setLifeTime( particles[i].getLifeTime() - particles[i].getDecay() );
particles[i].getPosition(xpos, ypos, zpos);
particles[i].getSpeed(xVel, yVel, zVel);
particles[i].getPosition(xpos += xVel, ypos += yVel, zpos += zVel);
particles[i].getSpeed(xVel, yVel -= 0.00007, zVel);
}
}
// Texture ///////////////////////////////////////////////////////////
// load a 256x256 RGB .RAW file as a texture
void ParticleSimulation::LoadTextureBMP(const char * filename, int wrap)
{
int width = 0, height = 0;
BYTE *data = NULL;
FILE *file = NULL;
// open texture data
file = fopen( filename, "rb" );
if ( file == NULL ) {
cout << "\nFile could not be opened." << endl;
return;
}
// allocate buffer
width = 256;
height = 256;
data = (BYTE *) malloc( width * height * 3 );
// read texture data
fread( data, width * height * 3, 1, file );
fclose(file);
// allocate a texture name
this->textureParticle = 0;
glGenTextures( 1, &this->textureParticle );
// select our current texture
glBindTexture( GL_TEXTURE_2D, this->textureParticle );
// select modulate to mix texture with color for shading
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
// when texture area is small, bilinear filter the closest MIP map
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_NEAREST );
// when texture area is large, bilinear filter the first MIP map
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
// if wrap is true, the texture wraps over at the edges (repeat)
// ... false, the texture ends at the edges (clamp)
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
wrap ? GL_REPEAT : GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
wrap ? GL_REPEAT : GL_CLAMP );
// build our texture MIP maps
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width,
height, GL_RGB, GL_UNSIGNED_BYTE, data );
// free buffer
free( data );
return;
}
void ParticleSimulation::FreeTexture(void )
{
glDeleteTextures(1, &this->textureParticle);
}
void ParticleSimulation::DrawAxis() {
char s1[10];
glPushMatrix();
glColor3f(1.0f, 0.0f, 0.0f);
sprintf(s1, "X-axis");
RenderBitmapString(50.0f, 0.0f, 0.0f, GLUT_BITMAP_HELVETICA_12, s1);
sprintf(s1, "Y-axis");
RenderBitmapString(0.0f, 50.0f, 0.0f, GLUT_BITMAP_HELVETICA_12, s1);
sprintf(s1, "Z-axis");
RenderBitmapString(0.0f, 0.0f, 50.0f, GLUT_BITMAP_HELVETICA_12, s1);
sprintf(s1, "Origin");
RenderBitmapString(0.0f, 0.0f, 0.0f, GLUT_BITMAP_HELVETICA_12, s1);
glPointSize(4.0f);
glColor3f(0.0f, 1.0f, 1.0f);
glBegin(GL_LINE_STRIP);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 50.0f, 0.0f);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(50.0f, 0.0f, 0.0f);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 50.0f);
glEnd();
glPopMatrix();
}
void ParticleSimulation::display(float dTime)
{
static int frame = 0;
//cout << "GlutFramework Display: Frame: " << frame << ", dt(sec): " << dTime << ", Position: " << position << endl;
++frame;
//cout << "Calling the DisplayObject Function" << endl;
//glTranslatef(0.0f, 0.0f, 0.0f);
//glutSolidTeapot(2.5);
DrawAxis(); //Aditya: Working with grayscale though
DisplayObjects(); //Aditya: Nothing is drawn
}
LoadTextureBMP() is being invoked (with its bevy of OpenGL calls) before you have an OpenGL context (via startFramework()).
You need a current context before issuing GL commands.
EDIT:
for(int i = 0; i <= this->numParticles; i++)
Stop that. You're accessing off the end of your allocated memory.
Do this:
for(int i = 0; i < this->numParticles; i++)
Notice the less-than instead of the less-than-or-equal. For C/C++ arrays of size N the only valid indexes are in the range [0, N-1]. Your <= will cause the for-loop to try to access element N.
That's bad.
EDIT2:
GlutFramework::init() enables lighting. This is altering the colors in your axis rendering in ParticleSimulation::DrawAxis(). Disable it in ParticleSimulation::display() via glDisable(GL_LIGHTING):
EDIT3:
This will do something but probably not what you expect:
glBegin(GL_TRIANGLE_STRIP);
glVertex2f(0.0,1.0); glVertex3f(xpos + 0.002, ypos + 0.002, zpos + 0.0); // top right
glVertex2f(0.0,0.0); glVertex3f(xpos - 0.002, ypos + 0.002, zpos + 0.0); // top left
glVertex2f(1.0,1.0); glVertex3f(xpos + 0.002, ypos - 0.002, zpos + 0.0); // bottom right
glVertex2f(1.0,0.0); glVertex3f(xpos - 0.002, ypos - 0.002, zpos + 0.0); // bottom left
glEnd();
You seem to think that glVertex2f() will somehow generate texture coordinates. It will not. You're looking for glTexCoord2f().
For drawing view-aligned triangles you'll want to look into billboarding.

Resources