PDA

View Full Version : Glee.h before Glut.h OR Glut.h before Glee.h



Savalia
06-08-2010, 11:02 PM
(Please disregard the continuation of my previous post - Thanks)
Ok, so I followed the suggestion of others and now have a new problem, I have a set of cpp/h files to handle tga files(the CTargaImage.h/.cpp & Wmain.cpp are from "Beginning OpenGL Game Programming" by D. Astle & K. Hawkins - I have used them on other occasions and the files are functional) I have a main that handles the window creation, and I have cpp/h files for the OpenGL effects. In a file I call glfx.cpp I do my openGL manipulations and multitexturing, but when I comple two included headers cause errors.

If I list glee.h before glut.h I get:

------ Build started: Project: display card, Configuration: Debug Win32 ------
Compiling...
glfx.cpp
Linking...
glfx.obj : error LNK2001: unresolved external symbol _pglActiveTexture
glfx.obj : error LNK2001: unresolved external symbol _pglMultiTexCoord2f
G:\C++\display card\Debug\display card.exe : fatal error LNK1120: 2 unresolved externals
Build log was saved at "file://g:\C++\display card\Debug\BuildLog.htm"
display card - 3 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

If I list glut before glee, I get:

------ Build started: Project: display card, Configuration: Debug Win32 ------
Compiling...
glfx.cpp
g:\c++\display card\glee.h(48) : fatal error C1189: #error : gl.h included before glee.h
Build log was saved at "file://g:\C++\display card\Debug\BuildLog.htm"
display card - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

the glfx.cpp file looks like:

[C++]
// Filename: GLFX.CPP
#ifndef WINDOWS
#include <windows.h>
#endif

#include <gl/glut.h>
#include "glee.h"


#include "glfx.h"
#include "CTargaImage.h"

//disable implisit float-double casting
#pragma warning(disable:4305)

//Constructor
glFx::glFx()
{
m_textureObjectOne = m_textureObjectTwo = 0;
}

//Destructor
glFx::~glFx()
{
}

//Initilize
bool glFx::initialize()
{
glClearColor(0.0, 0.0, 0.0, 0.0); //set background to black
glEnable(GL_TEXTURE_2D); //enable 2D texture use

m_textureOne = new CTargaImage; //1st texture
m_textureTwo = new CTargaImage; //2nd texture

//create the first texture object
if(!m_textureOne->Load("ace_club.tga"))
return false;

glActiveTexture(GL_TEXTURE0); //create texture unit 0
glGenTextures(1, &amp;m_textureObjectOne); //retrieve "unused" texture object
glBindTexture(GL_TEXTURE_2D, m_textureObjectOne); //bind texture object
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
//minimum required to set the MIN and MAG texture filters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//Now that the texture object is bound, specify a texture for it
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_textureOne->GetWidth(), m_textureOne->GetHeight(),
0, GL_RGB, GL_UNSIGNED_BYTE, m_textureOne->GetImage());
//end initialization of texture 1
m_textureOne->Release();

//create the second texture object
glActiveTexture(GL_TEXTURE1); //create texture unit 1
glEnable(GL_TEXTURE_2D);

if(!m_textureTwo->Load("deck_back.tga"))
return false;

glGenTextures(1, &amp;m_textureObjectTwo);
glBindTexture(GL_TEXTURE_2D, m_textureObjectTwo);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//Now that the texture object is bound, specify a texture for it
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_textureTwo->GetWidth(), m_textureTwo->GetHeight(),
0, GL_RGB, GL_UNSIGNED_BYTE, m_textureTwo->GetImage());
//end initialization of texture 2
m_textureTwo->Release();

//initialize the movement variables
m_angle = 0.0f;

return true;
}

//Shutdown
bool glFx::shutDown()
{
glDeleteTextures(1, &amp;m_textureObjectOne);
m_textureOne->Release();
delete m_textureOne;

glDeleteTextures(1, &amp;m_textureObjectTwo);
m_textureTwo->Release();
delete m_textureTwo;

return true;
}

//Establish the projection view
void glFx::setupProjection(int width, int height)
{
if(height == 0) //avoid divide by zero
height = 1;

glViewport(0, 0, width, height); //redimension the viewport
glMatrixMode(GL_PROJECTION); //projection matrix = current matrix
glLoadIdentity(); //reset projection matrix

//Calculate the windows aspect ratio
gluPerspective(60.0f, (GLfloat)width/(GLfloat)height, 1.0f, 1000.0f);

glMatrixMode(GL_MODELVIEW); //set Modelview projection
glLoadIdentity(); //reset modelview matrix

m_windowWidth = width; //define members for window size
m_windowHeight = height;
}

//Prepare the scene
void glFx::prepare(float dt)
{
m_angle += 0.5f; //used in object rotation
}

//creation of the objects to be displayed
void glFx::render()
{
//clear screen & depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

// move back 5 units and rotate about y axes
glTranslatef(0.0, 0.0, -5.0f);
glRotatef(m_angle, 0.0f, 1.0f, 0.0f);

// white
glColor3f(1.0f, 1.0f, 1.0f);

drawPlane();
}

void glFx::drawPlane()
{
glBegin(GL_QUADS);
//front texture of the playing card
glMultiTexCoord2f(GL_TEXTURE0, -2.0, -2.0); //texture 0 is defined counter-clockwise
//back texture of the playing card
glMultiTexCoord2f(GL_TEXTURE1, -2.0, -2.0); //texture 1 is defined clockwise
//surface coordinates
glVertex3f(-2.0, -2.0, 0.0);
glMultiTexCoord2f(GL_TEXTURE0, 2.0, -2.0); //starting from the lower left corner
glMultiTexCoord2f(GL_TEXTURE1, -2.0, 2.0); //of the object.
glVertex3f(2.0, -2.0, 0.0);
glMultiTexCoord2f(GL_TEXTURE0, 2.0, 2.0); //this would put texture 0 as the front
glMultiTexCoord2f(GL_TEXTURE1, 2.0, 2.0); // and texture 1 as the back of the object
glVertex3f(2.0, 2.0, 0.0);
glMultiTexCoord2f(GL_TEXTURE0, -2.0, 2.0);
glMultiTexCoord2f(GL_TEXTURE1, 2.0, -2.0);
glVertex3f(-2.0, 2.0, 0.0);
glEnd();
}
[/C++]

Any suggestions?( other than give up on game programming and try needlepoint! )

deek0146
06-09-2010, 05:41 AM
including glee first is correct. The other errors you have are unrelated - you're not linking libraries that include those two functions properly

Savalia
06-09-2010, 11:22 PM
OK so I still haven't got this to work (compile error free) but I'm adding the rest of the code ...

[Wmain.cpp]
/************************************************** ****************************
Filename: WMAIN.CPP
Date: 06/04/2010
Purpose: Utility program to display a complete playing card, both
front and back faces.
************************************************** ****************************/
#define WIN32_LEAN_AND_MEAN
#define WIN_EXTRA_LEAN

#include <windows.h>
//#include <gl.h>
//#include <glu.h>
#include "glFx.h"

//-----Global variables
bool EXIT = false;
long WINDOW_WIDTH = 800;
long WINDOW_HEIGHT = 600;
long WINDOW_BITS = 32;
bool FULL_SCREEN = false;
HDC hDC;
const char APP_TITLE[] = "Ogl: Display Card";
glFx *g_glRender = NULL;

void SetupPixelFormat(HDC hDC)
{
PIXELFORMATDESCRIPTOR pfd;
memset(&amp;pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); // size
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.nVersion = 1; // version
pfd.iPixelType = PFD_TYPE_RGBA; // color type
pfd.cColorBits = 32; // prefered color depth
pfd.cDepthBits = 24; // depth buffer
pfd.iLayerType = PFD_MAIN_PLANE; // main layer

int pixelFormat = ChoosePixelFormat(hDC, &amp;pfd);
SetPixelFormat(hDC, pixelFormat, &amp;pfd);
}

LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HDC hDC;
static HGLRC hRC;


//dispatch messages
switch(uMsg)
{
case WM_CREATE: //window creation
hDC = GetDC(hWnd);
SetupPixelFormat(hDC);
//SetupPallate();
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
break;

case WM_DESTROY: //window destroy
case WM_QUIT: //
case WM_CLOSE: //window is closing

//deselect render context and delete it
wglMakeCurrent(hDC, NULL);
wglDeleteContext(hRC);

//send WM_QUIT to message queue
PostQuitMessage(0);
break;

case WM_SIZE: //retrieve height and width
WINDOW_HEIGHT = HIWORD(lParam); //window height
WINDOW_WIDTH = LOWORD(lParam); //window width

g_glRender->SetupProjection(WINDOW_WIDTH, WINDOW_HEIGHT);

break;

case WM_ACTIVATEAPP: //active application
break;

case WM_PAINT: //paint window
PAINTSTRUCT ps;
BeginPaint(hWnd, &amp;ps);
EndPaint(hWnd, &amp;ps);
break;

case WM_LBUTTONDOWN: //left mouse button
break;

case WM_RBUTTONDOWN: //right mouse button
break;

case WM_MOUSEMOVE: //mouse movement
break;

case WM_LBUTTONUP: //left button release
break;

case WM_RBUTTONUP: //right button release
break;

case WM_KEYUP: //key released
break;

case WM_KEYDOWN:
int fwKeys;
LPARAM keyData;
fwKeys = (int)wParam; // virtual-key code
keyData = lParam; // key data

switch(fwKeys)
{
case VK_ESCAPE:
PostQuitMessage(0);
break;
default:
break;
}

break;

default:
break;
}

return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
WNDCLASSEX windowClass; //window class
HWND hwnd; //window handle
MSG msg; //message
DWORD dwExStyle; //Windows Extended Style
DWORD dwStyle; //Windows Style
RECT windowRect;

g_glRender = new glFx;

windowRect.left = (long) 0; //set the left value to zero
windowRect.right = (long)WINDOW_WIDTH; //set the right value to requested width
windowRect.top = (long)0; //set the top value to zero
windowRect.bottom = (long)WINDOW_HEIGHT;//set the bottom value to requested height

//fill out the window class structure
windowClass.cbSize = sizeof(WNDCLASSEX);
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = MainWindowProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = hInstance;
windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //default icon
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); //default arrow
windowClass.hbrBackground = NULL; //no background
windowClass.lpszMenuName = NULL; //no menu
windowClass.lpszClassName = "GLClass"; //
windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO); // window's logo small

//register the window class
if(!RegisterClassEx(&amp;windowClass))
return 0;

if(FULL_SCREEN) //check for full screen mode
{
DEVMODE dmScreenSettings; //device mode
memset(&amp;dmScreenSettings, 0, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = WINDOW_WIDTH; //screen width
dmScreenSettings.dmPelsHeight = WINDOW_HEIGHT; //screen height
dmScreenSettings.dmBitsPerPel = WINDOW_BITS; //bits per pixel
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

//
if(ChangeDisplaySettings(&amp;dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
//setting display mode failed, switch to windowed
MessageBox(NULL, "Display mode failed", NULL, MB_OK);
FULL_SCREEN = false;
}
}

if(FULL_SCREEN) //full screen still active
{
dwExStyle=WS_EX_APPWINDOW; // Window Extended Style
dwStyle=WS_POPUP; // Windows Style
ShowCursor(false); // Hide Mouse Pointer
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style
}

// Adjust Window To True Requested Size
AdjustWindowRectEx(&amp;windowRect, dwStyle, false, dwExStyle);

// class registered, so now create our window
hwnd = CreateWindowEx(NULL, // extended style
"GLClass", // class name
APP_TITLE, // app name
dwStyle | WS_CLIPCHILDREN |
WS_CLIPSIBLINGS,
0, 0, // x,y coordinate
windowRect.right - windowRect.left,
windowRect.bottom - windowRect.top, // width, height
NULL, // handle to parent
NULL, // handle to menu
hInstance, // application instance
NULL); // no extra params

hDC = GetDC(hwnd);

// check if window creation failed (hwnd would equal NULL)
if (!hwnd)
return 0;

ShowWindow(hwnd, SW_SHOW); // display the window
UpdateWindow(hwnd); // update the window

g_glRender->Init();

while (!EXIT)
{
g_glRender->Prepare(0.0f);
g_glRender->Render();
SwapBuffers(hDC);

while (PeekMessage (&amp;msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!GetMessage (&amp;msg, NULL, 0, 0))
{
EXIT = true;
break;
}

TranslateMessage (&amp;msg);
DispatchMessage (&amp;msg);
}
}

delete g_glRender;

if (FULL_SCREEN)
{
ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
ShowCursor(true); // Show Mouse Pointer
}

return (int)msg.wParam;

}
[/wmain.cpp]

next is
[glfx.h]
#ifndef __GL_COMPONENT
#define __GL_COMPONENT

#include "glee.h"

#define PI 3.14159
#define TWO_PI PI * 2.0
#define HALF_PI PI/2.0

class CTargaImage;

class glFx
{
public:
glFx();
virtual ~glFx();
bool Init();
bool Shutdown();
void SetupProjection(int width, int height);
void Prepare(float dt);
void Render();
void DrawPlane();

private:
int m_windowWidth;
int m_windowHeight;

CTargaImage *m_textureOne;
CTargaImage *m_textureTwo;

unsigned int m_textureObjectOne;
unsigned int m_textureObjectTwo;

float m_angle;
};

#endif


[/glfx.h]
next is
[glfx.cpp]
#ifndef WINDOWS
#include <windows.h>
#endif

#include "glee.h"
//#include <glext.h> //may not be needed

#include "glfx.h"
#include "CTargaImage.h"

//#include <gl/glu.h> //corrects error: error C3861: 'gluPerspective': identifier not found
//but adding this line generates 24 more errors

//disable implisit float-double casting
#pragma warning(disable:4305)

//Constructor
glFx::glFx()
{
m_textureObjectOne = m_textureObjectTwo = 0;
}

//Destructor
glFx::~glFx()
{
}

//Initilize
bool glFx::Init()
{
if(!GLeeInit())
return false;

glClearColor(0.0, 0.0, 0.0, 0.0); //set background to black
glEnable(GL_TEXTURE_2D); //enable 2D texture use

m_textureOne = new CTargaImage; //1st texture
m_textureTwo = new CTargaImage; //2nd texture

//create the first texture object
if(!m_textureOne->Load("ace_club.tga"))
return false;

// glActiveTexture(GL_TEXTURE0); //create texture unit 0
glGenTextures(1, &amp;m_textureObjectOne); //retrieve "unused" texture object
glBindTexture(GL_TEXTURE_2D, m_textureObjectOne); //bind texture object
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
//minimum required to set the MIN and MAG texture filters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//Now that the texture object is bound, specify a texture for it
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_textureOne->GetWidth(), m_textureOne->GetHeight(),
0, GL_RGB, GL_UNSIGNED_BYTE, m_textureOne->GetImage());
//end initialization of texture 1
m_textureOne->Release();

//create the second texture object
// glActiveTexture(GL_TEXTURE1); //create texture unit 1
// glEnable(GL_TEXTURE_2D);

if(!m_textureTwo->Load("deck_back.tga"))
return false;

glGenTextures(1, &amp;m_textureObjectTwo);
glBindTexture(GL_TEXTURE_2D, m_textureObjectTwo);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//Now that the texture object is bound, specify a texture for it
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_textureTwo->GetWidth(), m_textureTwo->GetHeight(),
0, GL_RGB, GL_UNSIGNED_BYTE, m_textureTwo->GetImage());
//end initialization of texture 2
m_textureTwo->Release();

//initialize the movement variables
m_angle = 0.0f;

return true;
}

//Shutdown
bool glFx::Shutdown()
{
glDeleteTextures(1, &amp;m_textureObjectOne);
m_textureOne->Release();
delete m_textureOne;

glDeleteTextures(1, &amp;m_textureObjectTwo);
m_textureTwo->Release();
delete m_textureTwo;

return true;
}

//Establish the projection view
void glFx::SetupProjection(int width, int height)
{
if(height == 0) //avoid divide by zero
height = 1;

glViewport(0, 0, width, height); //redimension the viewport
glMatrixMode(GL_PROJECTION); //projection matrix = current matrix
glLoadIdentity(); //reset projection matrix

//Calculate the windows aspect ratio
gluPerspective(60.0f, (GLfloat)width/(GLfloat)height, 1.0f, 1000.0f);

glMatrixMode(GL_MODELVIEW); //set Modelview projection
glLoadIdentity(); //reset modelview matrix

m_windowWidth = width; //define members for window size
m_windowHeight = height;
}

//Prepare the scene
void glFx::Prepare(float dt)
{
m_angle += 0.5f; //used in object rotation
}

//creation of the objects to be displayed
void glFx::Render()
{
//clear screen & depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

// move back 5 units and rotate about y axes
glTranslatef(0.0, 0.0, -5.0f);
glRotatef(m_angle, 0.0f, 1.0f, 0.0f);

// white
glColor3f(1.0f, 1.0f, 1.0f);

DrawPlane();
}

void glFx::DrawPlane()
{
glBegin(GL_QUADS);
//front texture of the playing card
glMultiTexCoord2f(GL_TEXTURE0, -2.0, -2.0); //texture 0 is defined counter-clockwise
//back texture of the playing card
glMultiTexCoord2f(GL_TEXTURE1, -2.0, -2.0); //texture 1 is defined clockwise
//surface coordinates
glVertex3f(-2.0, -2.0, 0.0);
glMultiTexCoord2f(GL_TEXTURE0, 2.0, -2.0); //starting from the lower left corner
glMultiTexCoord2f(GL_TEXTURE1, -2.0, 2.0); //of the object.
glVertex3f(2.0, -2.0, 0.0);
glMultiTexCoord2f(GL_TEXTURE0, 2.0, 2.0); //this would put texture 0 as the front
glMultiTexCoord2f(GL_TEXTURE1, 2.0, 2.0); // and texture 1 as the back of the object
glVertex3f(2.0, 2.0, 0.0);
glMultiTexCoord2f(GL_TEXTURE0, -2.0, 2.0);
glMultiTexCoord2f(GL_TEXTURE1, 2.0, -2.0);
glVertex3f(-2.0, 2.0, 0.0);
glEnd();
}
[/glfx.cpp]
and the tga handlers are
[ctargaimage.h]

#ifndef _TARGA_LIB
#define _TARGA_LIB

enum TGATypes
{
TGA_NODATA = 0,
TGA_INDEXED = 1,
TGA_RGB = 2,
TGA_GRAYSCALE = 3,
TGA_INDEXED_RLE = 9,
TGA_RGB_RLE = 10,
TGA_GRAYSCALE_RLE = 11,
};

//Image data formats
#define IMAGE_RGB 0
#define IMAGE_RGBA 1
#define IMAGE_LUMINANCE 2

//Image data types
#define IMAGE_DATA_UNSIGNED_BYTE 0

//Pixel data transfer from file to screen:
//These masks are AND'd wirh the imageDesc in the TGA header,
//bit 4 is left-to-right ordering, bit 5 is top-to-bottom
#define BOTTOM_LEFT 0x00 //first pixel is bottom left corner
#define BOTTON_RIGHT 0x10 //first pixel is bottom right corner
#define TOP_LEFT 0x20 //first pixel is top left corner
#define TOP_RIGHT 0x30 //first pixel is top right corner

//TGA header
struct tgaheader_t
{
unsigned char idLength;
unsigned char colorMapType;
unsigned char imageTypeCode;
unsigned char colorMapSpec[5];
unsigned short xOrigin;
unsigned short yOrigin;
unsigned short width;
unsigned short height;
unsigned char bpp;
unsigned char imageDesc;
};

struct rgba_t
{
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
};

struct rgb_t
{
unsigned char r;
unsigned char g;
unsigned char b;
};

class CTargaImage
{
public:
CTargaImage(); //constructor
virtual ~CTargaImage(); //destructor

//load/unload
bool Load(const char *filename); //Get file
void Release(); //de-allocate mem for file

//Proceessing
bool FlipVertical(); //invert image vertically

//Get/Set accessors
unsigned short GetWidth() { return m_width; }
unsigned short GetHeight() { return m_height; }
unsigned char GetImageFormat() { return m_imageDataFormat; }

//Convert RGB format to RGBA format and vice versa
bool ConvertRGBAToRGB();
bool ConvertRGBToRGBA(unsigned char alphaValue);

//returns the current image data
unsigned char *GetImage() { return m_PtrImageData; }

private:
unsigned char m_colorDepth;
unsigned char m_imageDataType;
unsigned char m_imageDataFormat;
unsigned char *m_PtrImageData;
unsigned short m_width;
unsigned short m_height;
unsigned short m_imageSize;

//Swap the red and blue components of the image data
void SwapRedBlue();
};

#endif
[/ctargaimage.h]
and
[ctargaimage.cpp]

#include <iostream>
#include "CTargaImage.h"

#pragma warning (disable:4996)

//Constructor
CTargaImage::CTargaImage() : m_PtrImageData(NULL)
{
}

//Destructor
CTargaImage::~CTargaImage()
{
Release();
}

//Swap Blue and Red
void CTargaImage::SwapRedBlue()
{
switch (m_colorDepth)
{
case 32:
{
unsigned char temp;
rgba_t* source = (rgba_t*)m_PtrImageData;

for(int pixel = 0; pixel < (m_width * m_height); ++pixel)
{
temp = source[pixel].b;
source[pixel].b = source[pixel].r;
source[pixel].r = temp;
}
} break;
case 24:
{
unsigned char temp;
rgb_t* source = (rgb_t*)m_PtrImageData;

for(int pixel = 0; pixel < (m_width * m_height); ++pixel)
{
temp = source[pixel].b;
source[pixel].b = source[pixel].r;
source[pixel].r = temp;
}
} break;
default: //ignore other color depths
break;
}
}

//Load the imaage file
bool CTargaImage::Load(const char *filename)
{
FILE *pFile = fopen(filename, "rb");

if (!pFile)
return false;

tgaheader_t tgaHeader;

// read the TGA header
fread(&amp;tgaHeader, 1, sizeof(tgaheader_t), pFile);

// see if the image type is supported (RGB, RGB RLE, GRAYSCALE, GRAYSCALE RLE)
if ( ((tgaHeader.imageTypeCode != TGA_RGB) &amp;&amp; (tgaHeader.imageTypeCode != TGA_GRAYSCALE) &amp;&amp;
(tgaHeader.imageTypeCode != TGA_RGB_RLE) &amp;&amp; (tgaHeader.imageTypeCode != TGA_GRAYSCALE_RLE)) ||
tgaHeader.colorMapType != 0)
{
fclose(pFile);
return false;
}

// get image width and height
m_width = tgaHeader.width;
m_height = tgaHeader.height;

// colormode -> 3 = BGR, 4 = BGRA
int colorMode = tgaHeader.bpp / 8;

// we don't handle less than 24 bit
if (colorMode < 3)
{
fclose(pFile);
return false;
}

m_imageSize = m_width * m_height * colorMode;

// allocate memory for TGA image data
m_PtrImageData = new unsigned char[m_imageSize];

// skip past the id if there is one
if (tgaHeader.idLength > 0)
fseek(pFile, SEEK_CUR, tgaHeader.idLength);

// read image data
if (tgaHeader.imageTypeCode == TGA_RGB || tgaHeader.imageTypeCode == TGA_GRAYSCALE)
{
fread(m_PtrImageData, 1, m_imageSize, pFile);
}
else
{
// this is an RLE compressed image
unsigned char id;
unsigned char length;
rgba_t color = { 0, 0, 0, 0 };
unsigned int i = 0;

while (i < m_imageSize)
{
id = fgetc(pFile);

// see if this is run length data
if (id >= 128)// & 0x80)
{
// find the run length
length = (unsigned char)(id - 127);

// next 3 (or 4) bytes are the repeated values
color.b = (unsigned char)fgetc(pFile);
color.g = (unsigned char)fgetc(pFile);
color.r = (unsigned char)fgetc(pFile);

if (colorMode == 4)
color.a = (unsigned char)fgetc(pFile);

// save everything in this run
while (length > 0)
{
m_PtrImageData[i++] = color.b;
m_PtrImageData[i++] = color.g;
m_PtrImageData[i++] = color.r;

if (colorMode == 4)
m_PtrImageData[i++] = color.a;

--length;
}
}
else
{
// the number of non RLE pixels
length = unsigned char(id + 1);

while (length > 0)
{
color.b = (unsigned char)fgetc(pFile);
color.g = (unsigned char)fgetc(pFile);
color.r = (unsigned char)fgetc(pFile);

if (colorMode == 4)
color.a = (unsigned char)fgetc(pFile);

m_PtrImageData[i++] = color.b;
m_PtrImageData[i++] = color.g;
m_PtrImageData[i++] = color.r;

if (colorMode == 4)
m_PtrImageData[i++] = color.a;

--length;
}
}
}
}

fclose(pFile);

switch(tgaHeader.imageTypeCode)
{
case TGA_RGB:
case TGA_RGB_RLE:
if (3 == colorMode)
{
m_imageDataFormat = IMAGE_RGB;
m_imageDataType = IMAGE_DATA_UNSIGNED_BYTE;
m_colorDepth = 24;
}
else
{
m_imageDataFormat = IMAGE_RGBA;
m_imageDataType = IMAGE_DATA_UNSIGNED_BYTE;
m_colorDepth = 32;
}
break;

case TGA_GRAYSCALE:
case TGA_GRAYSCALE_RLE:
m_imageDataFormat = IMAGE_LUMINANCE;
m_imageDataType = IMAGE_DATA_UNSIGNED_BYTE;
m_colorDepth = 8;
break;
}

if ((tgaHeader.imageDesc & TOP_LEFT) == TOP_LEFT)
FlipVertical();

// swap the red and blue components in the image data
SwapRedBlue();

return (m_PtrImageData != NULL);
}

bool CTargaImage::FlipVertical()
{
if (!m_PtrImageData)
return false;

if (m_colorDepth == 32)
{
rgba_t* tmpBits = new rgba_t[m_width];
if (!tmpBits)
return false;

int lineWidth = m_width * 4;

rgba_t* top = (rgba_t*)m_PtrImageData;
rgba_t* bottom = (rgba_t*)(m_PtrImageData + lineWidth*(m_height-1));

for (int i = 0; i < (m_height / 2); ++i)
{
memcpy(tmpBits, top, lineWidth);
memcpy(top, bottom, lineWidth);
memcpy(bottom, tmpBits, lineWidth);

top = (rgba_t*)((unsigned char*)top + lineWidth);
bottom = (rgba_t* )((unsigned char*)bottom - lineWidth);
}

delete [] tmpBits;
tmpBits = 0;
}
else if (m_colorDepth == 24)
{
rgb_t* tmpBits = new rgb_t[m_width];
if (!tmpBits)
return false;

int lineWidth = m_width * 3;

rgb_t* top = (rgb_t*)m_PtrImageData;
rgb_t* bottom = (rgb_t*)(m_PtrImageData + lineWidth*(m_height-1));

for (int i = 0; i < (m_height / 2); ++i)
{
memcpy(tmpBits, top, lineWidth);
memcpy(top, bottom, lineWidth);
memcpy(bottom, tmpBits, lineWidth);

top = (rgb_t*)((unsigned char*)top + lineWidth);
bottom = (rgb_t*)((unsigned char*)bottom - lineWidth);
}

delete [] tmpBits;
tmpBits = 0;
}

return true;
}

//De-allocate the storage for the file
void CTargaImage::Release()
{
delete [] m_PtrImageData;
m_PtrImageData = NULL;
}

//Add the alpha channel
bool CTargaImage::ConvertRGBToRGBA(unsigned char alphaValue)
{
if ((m_colorDepth == 24) &amp;&amp; (m_imageDataFormat == IMAGE_RGB))
{
rgba_t *newImage = new rgba_t[m_width * m_height];

if (!newImage)
return false;

rgba_t *dest = newImage;
rgb_t *src = (rgb_t*)m_PtrImageData;

for (int x = 0; x < m_height; x++)
{
for (int y = 0; y < m_width; y++)
{
dest->r = src->r;
dest->g = src->g;
dest->b = src->b;
dest->a = alphaValue;

++src;
++dest;
}
}

delete [] m_PtrImageData;
m_PtrImageData = (unsigned char*)newImage;

m_colorDepth = 32;
m_imageDataType = IMAGE_DATA_UNSIGNED_BYTE;
m_imageDataFormat = IMAGE_RGBA;

return true;
}

return false;
}

//Remove the alpha channel
bool CTargaImage::ConvertRGBAToRGB()
{
if ((m_colorDepth == 32) &amp;&amp; (m_imageDataFormat == IMAGE_RGBA))
{
rgb_t *newImage = new rgb_t[m_width * m_height];

if (!newImage)
return false;

rgb_t *dest = newImage;
rgba_t *src = (rgba_t*)m_PtrImageData;

for (int x = 0; x < m_height; x++)
{
for (int y = 0; y < m_width; y++)
{
dest->r = src->r;
dest->g = src->g;
dest->b = src->b;

++src;
++dest;
}
}

delete [] m_PtrImageData;
m_PtrImageData = (unsigned char*)newImage;

m_colorDepth = 24;
m_imageDataType = IMAGE_DATA_UNSIGNED_BYTE;
m_imageDataFormat = IMAGE_RGB;

return true;
}

return false;
}
[/ctargaimage.cpp]
Any help, suggestions or criticism is welcome, hopefully someone will lead me in the right direction

Savalia
06-09-2010, 11:27 PM
Post Script
- the way I have my header libraries set up for OpenGL is

instead of <gl/gl.h> I just type <gl.h> (I dragged/dropped the OpenGL files directly into the include folder)
-it seemed to make sense at the time I did it.