NOGDUS

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



: Getting into OpenGL with GLUT on Linux
: Richard Marks 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)

:

// 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?


Sorry, the copyright must be in the template.
Please notify this forum's administrator that this site is missing the copyright message for SMF so they can rectify the situation. Display of copyright is a legal requirement. For more information on this please visit the Simple Machines website.