NOGDUS

Articles, Tutorials, and other things. => General Game Programming => Topic started by: Richard Marks on December 17, 2008, 03:29:18 AM



Title: Getting into OpenGL with GLUT on Linux
Post by: Richard Marks on December 17, 2008, 03:29:18 AM
(http://www.ccpssolutions.com/storage/richard/opengl/freeglutdemo2.png) (http://www.ccpssolutions.com/storage/richard/opengl/freeglutdemo2.png)

Code:

// CODESTYLE: v2.0

// main.cpp
// Project: Free-GLUT Demo #2 (GLUTDemo2)
// Author: Richard Marks

#include <GL/gl.h>
#include <GL/glut.h>
#include <GL/glu.h>

#include <cstdio>
#include <cstdlib>
#include <cstring>

namespace ENGINE
{
namespace CORE3D
{
typedef struct Vertex_Type
{
float x_, y_, z_, u_, v_;
} Vertex;

typedef struct Triangle_Type
{
Vertex v_[3];
} Triangle;

struct Texture
{
int width_;
int height_;
unsigned char* data_;
Texture()
{
width_ = 0;
height_ = 0;
data_ = 0;
};

~Texture()
{
if (data_)
{
delete [] data_;
data_ = 0;
width_ = 0;
height_ = 0;
}
}
};

class TextureLoader
{
public:
static bool LoadBMP(const char* fileName, Texture& texture);
private:
TextureLoader();
};

bool TextureLoader::LoadBMP(const char* fileName, Texture& texture)
{
FILE* fp = fopen(fileName, "rb");
if (fp)
{
unsigned int fileType = 0;
//fprintf(stderr, "Reading File Type: File Byte Ptr: %d\n", ftell(fp));
if (!fread(&fileType, sizeof(unsigned char), 2, fp))
{
fprintf(stderr, "Error reading file!\n");
return false;
}

if (0x4D42 != fileType)
{
fprintf(stderr, "Error: Not a valid BMP bitmap file!\n");
return false;
}

// locate image data
fseek(fp, 0x8, SEEK_CUR);
unsigned long imageBytesOffset = 0;
//fprintf(stderr, "Reading Image Bytes Offset: File Byte Ptr: %d\n", ftell(fp));
if (!fread(&imageBytesOffset, sizeof(unsigned char), 4, fp))
{
fprintf(stderr, "Error reading file!\n");
return false;
}

// get size of the image
fseek(fp, 0x4, SEEK_CUR);
//fprintf(stderr, "Reading Image Width: File Byte Ptr: %d\n", ftell(fp));
if (!fread(&texture.width_, sizeof(unsigned char), 4, fp))
{
fprintf(stderr, "Error reading file!\n");
return false;
}

//fprintf(stderr, "Reading Image Height: File Byte Ptr: %d\n", ftell(fp));
if (!fread(&texture.height_, sizeof(unsigned char), 4, fp))
{
fprintf(stderr, "Error reading file!\n");
return false;
}

//fprintf(stderr, "Image Size %dx%d\n", texture.width_, texture.height_);

//fprintf(stderr, "Reading Color Planes: File Byte Ptr: %d\n", ftell(fp));
unsigned int imageColorPlanes = 0;
if (!fread(&imageColorPlanes, sizeof(unsigned char), 2, fp))
{
fprintf(stderr, "Error reading file!\n");
return false;
}

if (0x1 != imageColorPlanes)
{
fprintf(stderr, "Error: Color planes must be equal to 0x1 not 0x%X!\n", imageColorPlanes);
return false;
}

// get the color depth
unsigned int imageColorDepth = 0;
//fprintf(stderr, "Reading Color Depth: File Byte Ptr: %d\n", ftell(fp));
if (!fread(&imageColorDepth, sizeof(unsigned char), 2, fp))
{
fprintf(stderr, "Error reading file!\n");
return false;
}

// we only want 24-bit BMP files
if (0x18 != imageColorDepth)
{
fprintf(stderr, "Error: Color depth must be 24-bit! %d-bit is not supported!\n", imageColorDepth);
return false;
}

// calculate the size of the image data
unsigned long imageDataSize = 0x3 * (texture.width_ * texture.height_);

// allocate the image data
texture.data_ = new unsigned char [imageDataSize];

// jump to the image data
fseek(fp, imageBytesOffset, SEEK_SET);
//fprintf(stderr, "Reading Image Data: File Byte Ptr: %d\n", ftell(fp));

// load the image data
if (!fread(texture.data_, sizeof(unsigned char), imageDataSize, fp))
{
fprintf(stderr, "Error reading file!\n");
return false;
}

// convert loaded BGR to RGB
for (unsigned long index = 0; index < imageDataSize; index += 0x3)
{
unsigned char temp = texture.data_[index];
texture.data_[index] = texture.data_[index + 0x2];
texture.data_[index + 0x2] = temp;
}

fclose(fp);
return true;
}

fprintf(stderr, "Error opening file %s!\n", fileName);
return false;
}

} // end namespace
} // end namespace

namespace GLUTDemo2
{
class Demo
{
public:
~Demo();
static Demo* GetInstance();

GLuint GetTexture(int index);

bool Initialize(int argc, char* argv[]);
void Execute();

static void RenderScene();
static void ResizeScene(int width, int height);

private:
Demo();

GLuint* textures_;
};

Demo::Demo()
{
textures_ = new GLuint [1];
}

Demo::~Demo()
{
delete [] textures_;
textures_ = 0;
}

Demo* Demo::GetInstance()
{
static Demo instance;
return &instance;
}

GLuint Demo::GetTexture(int index)
{
return textures_[index];
}

bool Demo::Initialize(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(640, 480);
glutInitWindowPosition(64, 64);
glutCreateWindow("Free-GLUT Demo #2");

glutDisplayFunc(Demo::RenderScene);
glutIdleFunc(Demo::RenderScene);
glutReshapeFunc(Demo::ResizeScene);


// load up textures
ENGINE::CORE3D::Texture texture;
if (!ENGINE::CORE3D::TextureLoader::LoadBMP("texture1.bmp", texture))
{
fprintf(stderr, "Could not load texture1.bmp!\n");
return false;
}

glGenTextures(1, &textures_[0]);
glBindTexture(GL_TEXTURE_2D, textures_[0]);
glTexImage2D(GL_TEXTURE_2D, 0, 3, texture.width_, texture.height_, 0, GL_RGB, GL_UNSIGNED_BYTE, texture.data_);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);


glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);

glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

return true;
}

void Demo::Execute()
{
glutMainLoop();
}

void Demo::ResizeScene(int width, int height)
{
height = (0 == height) ? 1 : height;

glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(
45.0f,
static_cast<GLfloat>(width) / static_cast<GLfloat>(height),
0.1f,
100.0f);
glMatrixMode(GL_MODELVIEW);
}

void Demo::RenderScene()
{
static GLfloat rotationAngle[3] = {0.0f, 0.0f, 0.0f};

GLuint texture = GLUTDemo2::Demo::GetInstance()->GetTexture(0);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

glTranslatef(0.0f, 0.0f, -5.0f);
glRotatef(rotationAngle[0], 1.0f, 0.0f, 0.0f);
glRotatef(rotationAngle[1], 0.0f, 1.0f, 0.0f);
glRotatef(rotationAngle[2], 0.0f, 0.0f, 1.0f);

glBindTexture(GL_TEXTURE_2D, texture);

glBegin(GL_QUADS);
// Front Face
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f); // Top Left Of The Texture and Quad
// Back Face
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad
// Top Face
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f); // Top Right Of The Texture and Quad
// Bottom Face
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f); // Bottom Right Of The Texture and Quad
// Right face
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f); // Bottom Left Of The Texture and Quad
// Left Face
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f); // Top Left Of The Texture and Quad
glEnd();

rotationAngle[0] += 0.3f;
rotationAngle[1] += 0.2f;
rotationAngle[2] += 0.4f;

glutSwapBuffers();
}

} // end namespace


int main(int argc, char* argv[])
{
if (GLUTDemo2::Demo::GetInstance()->Initialize(argc, argv))
{
GLUTDemo2::Demo::GetInstance()->Execute();
}
return 0;
}

The texture bitmaps need to be 64x64, 128x128, or 256x256 and 24-bit. Use GIMP and be sure to save as 24-bit BMP.

Pretty easy eh?