I'm trying to write my first OpenGL app.
It's using a TGA Loader from [url=http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=33]Here.[/url]
The code compiles fine, but I never get anything to actually display on my mesh. Here's what it looks like:
[img]http://i51.tinypic.com/33bhji9.png[/img]
Here's code:
[b]Sample.cpp (Entry Point)[/b]
[code]
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <math.h> //Math Library
#include <stdio.h> //I/O Library
#include "texture.h"
bool LoadTGA(Texture *, char*); //Function Prototype to load TGA textures
HWND hWnd;
HDC hDC;
HGLRC hRC;
bool keys[256];
bool blend; //Blending On/Off
bool bPressed; //Is B Pressed?
bool fPressed; //Is F Pressed?
bool lPressed; //Is L pressed?
bool pgUpPressed;
bool pgDnPressed;
bool light;
//Lighting
GLfloat LightAmbient[] = { 0.5f, 0.5f, 0.5f, 1.0f }; //Ambient Light Values
GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; //Diffuse Light
GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f, 1.0f };
//Textures
GLuint filter; //Filter to use
Texture texture[2]; //Store up to TWO WHOLE TEXTURES
GLfloat xRot; //X Rotation
GLfloat yRot; //Y rotation
GLfloat xSpeed; //X Speed
GLfloat ySpeed;
GLfloat zDepth = -5.0f; //Depth in scene objects are
GLfloat walkbias = 0;
GLfloat walkbiasangle = 0;
GLfloat lookupdown = 0.0f;
const float piover180 = 0.0174532925f;
float heading;
float xPos;
float yPos;
float zPos;
typedef struct tagVERTEX
{
float x, y, z; //3d coords
float u, v; //Texture Coords
} VERTEX;
typedef struct tagTRIANGLE
{
VERTEX vertex[3]; //Hold the 3 verticies
} TRIANGLE; //Call it Triangle
typedef struct tagSECTOR //Sector
{
int numTriangles; //Hold the #Tri's in the sector
TRIANGLE* triangle; //Pointer to array of triangles
} SECTOR;
SECTOR sector1;
void readstr( FILE *f, char *string ) //Read lines from our text file
{
do
{
fgets( string, 255, f ); //Read one line
} while ((string[0] == '/') || (string[0] == '\n')); //See if it's worth processing
return;
}
void SetupWorld()
{
FILE *filein; //File to use
filein = fopen( "data/world.txt" , "rt" ); //Open it
int numTriangles; //Number of triagnles in sector
char oneline[255]; //String to store the data in
float x, y, z, u, v; //3d and Texture Coordinates
//Read our data
readstr( filein, oneline );
sscanf( oneline, "NUMPOLLIES %d\n", &numTriangles);
sector1.triangle = new TRIANGLE[numTriangles];
sector1.numTriangles = numTriangles;
//Step through each triangle in sector
for (int triloop = 0; triloop < numTriangles; triloop++ )
{
//Step through each vertex in triangle
for (int vertloop = 0; vertloop < 3; vertloop ++)
{
readstr(filein, oneline);
//Find data and place it into values
sscanf( oneline, "%f %f %f %f %f", &x, &y, &z, &u, &v );
//Store them
sector1.triangle[triloop].vertex[vertloop].x = x;
sector1.triangle[triloop].vertex[vertloop].y = y;
sector1.triangle[triloop].vertex[vertloop].z = z;
sector1.triangle[triloop].vertex[vertloop].u = u;
sector1.triangle[triloop].vertex[vertloop].v = v;
}
}
fclose( filein );
return;
}
int LoadGLTextures()
{
int Status = false; //Hasn't loaded yet
//Load the TGA, check for errors
if (LoadTGA(&texture[0], "Data/Uncompressed.tga") &&
LoadTGA(&texture[1], "Data/Uncompressed.tga"))
{
Status = true;
for (int loop = 0; loop < 1; loop++ )
{
//Generate texture info from TGA
glGenTextures( 1, &texture[loop].texID); //Create a Texture via ID
glBindTexture( GL_TEXTURE_2D, texture[loop].texID );
glTexImage2D( GL_TEXTURE_2D, 0, texture[loop].bpp / 8, texture[loop].width, texture[loop].height, 0, texture[loop].type, GL_UNSIGNED_BYTE, texture[loop].imageData );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
if (texture[loop].imageData ) //Make sure it exists
{
free(texture[loop].imageData); //Free the memory the texture had now that it's loaded
}
}
}
return Status;
}
// Set up pixel format for graphics initialization
void SetupPixelFormat()
{
PIXELFORMATDESCRIPTOR pfd, *ppfd;
int pixelformat;
ppfd = &pfd;
ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
ppfd->nVersion = 1;
ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_TYPE_RGBA;
ppfd->dwLayerMask = PFD_MAIN_PLANE;
ppfd->iPixelType = PFD_TYPE_COLORINDEX;
ppfd->cColorBits = 16;
ppfd->cDepthBits = 16;
ppfd->cAccumBits = 0;
ppfd->cStencilBits = 0;
pixelformat = ChoosePixelFormat(hDC, ppfd);
SetPixelFormat(hDC, pixelformat, ppfd);
}
// Initialize OpenGL graphics
void InitGraphics()
{
if (!LoadGLTextures())
{
return;
}
hDC = GetDC(hWnd);
SetupPixelFormat();
glEnable( GL_TEXTURE_2D );
glShadeModel( GL_SMOOTH );
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
glClearColor(0, 0, 0, 0.5);
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc( GL_LEQUAL );
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glLightfv( GL_LIGHT1, GL_AMBIENT, LightAmbient );
glLightfv( GL_LIGHT1, GL_DIFFUSE, LightDiffuse );
//Position of above light
glLightfv( GL_LIGHT1, GL_POSITION, LightPosition );
glEnable( GL_LIGHT1 );
SetupWorld();
}
// Resize graphics to fit window
void ResizeGraphics()
{
// Get new window size
RECT rect;
int width, height;
GLfloat aspect;
GetClientRect(hWnd, &rect);
width = rect.right;
height = rect.bottom;
aspect = (GLfloat)width / height;
// Adjust graphics to window size
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, aspect, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}
float spin;
// Draw frame
void DrawGraphics()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Set location in front of camera
glLoadIdentity();
GLfloat x_m, y_m, z_m, u_m, v_m; //Floats for temp values
GLfloat xtrans = -xPos; //X translation
GLfloat ztrans = -zPos; //Z translation
GLfloat ytrans = -walkbias -0.02f - 0.5; //Used for bobbing view
GLfloat sceneroty = 360.0f - yRot;
int numtriangles;
glRotatef( lookupdown, 1.0f, 0, 0);
glRotatef( sceneroty, 0, 1.0f, 0); //Rotate Y
glTranslatef( xtrans, ytrans, ztrans);
//glBindTexture( GL_TEXTURE_2D, texture[filter]); //Select a texture based on filter
numtriangles = sector1.numTriangles;
//Process each triangle
for (int loop_m = 0; loop_m < numtriangles; loop_m++)
{
glBindTexture( GL_TEXTURE_2D, texture[0].texID );
glBegin( GL_TRIANGLES );
glNormal3f( 0.0f, 0.0f, 1.0f ); //Normal pointing forwards
x_m = sector1.triangle[loop_m].vertex[0].x; //1st Point - X
y_m = sector1.triangle[loop_m].vertex[0].y; //1st Point - Y
z_m = sector1.triangle[loop_m].vertex[0].z; //1st Point - Z
u_m = sector1.triangle[loop_m].vertex[0].u; //U coordiante
v_m = sector1.triangle[loop_m].vertex[0].v; //V Coordinate
glTexCoord2f( u_m, v_m);
glVertex3f( x_m, y_m, z_m );
x_m = sector1.triangle[loop_m].vertex[1].x; //2nd Point - X
y_m = sector1.triangle[loop_m].vertex[1].y; //2nd Point - Y
z_m = sector1.triangle[loop_m].vertex[1].z; //2nd Point - Z
u_m = sector1.triangle[loop_m].vertex[1].u; //U coordiante
v_m = sector1.triangle[loop_m].vertex[1].v; //V Coordinate
glTexCoord2f( u_m, v_m);
glVertex3f( x_m, y_m, z_m );
x_m = sector1.triangle[loop_m].vertex[2].x; //3rd Point - X
y_m = sector1.triangle[loop_m].vertex[2].y; //3rd Point - Y
z_m = sector1.triangle[loop_m].vertex[2].z; //3rd Point - Z
u_m = sector1.triangle[loop_m].vertex[2].u; //U coordiante
v_m = sector1.triangle[loop_m].vertex[2].v; //V Coordinate
glTexCoord2f( u_m, v_m);
glVertex3f( x_m, y_m, z_m );
glEnd();
}
/*
for (int loop=0; loop<20; loop++) // Loop Of 20
{
glPushMatrix(); // Push The Matrix
glRotatef(spin+loop*18.0f,1.0f,0.0f,0.0f); // Rotate On The X-Axis (Up - Down)
glTranslatef(-2.0f,2.0f,0.0f); // Translate 2 Units Left And 2 Up
glBindTexture(GL_TEXTURE_2D, texture[0].texID); // ( CHANGE )
glBegin(GL_QUADS); // Draw Our Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 0.0f);
glEnd(); // Done Drawing The Quad
glPopMatrix(); // Pop The Matrix
glPushMatrix(); // Push The Matrix
glTranslatef(2.0f,0.0f,0.0f); // Translate 2 Units To The Right
glRotatef(spin+loop*36.0f,0.0f,1.0f,0.0f); // Rotate On The Y-Axis (Left - Right)
glTranslatef(1.0f,0.0f,0.0f); // Move One Unit Right
glBindTexture(GL_TEXTURE_2D, texture[1].texID); // ( CHANGE )
glBegin(GL_QUADS); // Draw Our Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, -1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, -1.0f, 0.0f);
glEnd(); // Done Drawing The Quad
glPopMatrix(); // Pop The Matrix
}
*/
// Show the new scene
SwapBuffers(hDC);
}
// Handle window events and messages
LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_SIZE:
ResizeGraphics();
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_KEYDOWN: // Is A Key Being Held Down?
{
keys[wParam] = TRUE; // If So, Mark It As TRUE
return 0; // Jump Back
}
case WM_KEYUP: // Has A Key Been Released?
{
keys[wParam] = FALSE; // If So, Mark It As FALSE
return 0; // Jump Back
}
// Default event handler
default:
return DefWindowProc (hWnd, uMsg, wParam, lParam);
break;
}
return 1;
}
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
const LPCWSTR appname = TEXT("OpenGL Sample");
WNDCLASS wndclass;
MSG msg;
// Define the window class
wndclass.style = 0;
wndclass.lpfnWndProc = (WNDPROC)MainWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(hInstance, appname);
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wndclass.lpszMenuName = appname;
wndclass.lpszClassName = appname;
// Register the window class
if (!RegisterClass(&wndclass)) return FALSE;
// Create the window
hWnd = CreateWindow(
appname,
appname,
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
CW_USEDEFAULT,
CW_USEDEFAULT,
800,
600,
NULL,
NULL,
hInstance,
NULL);
if (!hWnd) return FALSE;
// Initialize OpenGL
InitGraphics();
// Display the window
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Event loop
while (1)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == TRUE)
{
if (!GetMessage(&msg, NULL, 0, 0)) return TRUE;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
DrawGraphics();
if (keys['L'] && !lPressed)
{
lPressed = true;
light = !light;
if (!light)
{
glDisable( GL_LIGHTING );
}
else
{
glEnable( GL_LIGHTING );
}
}
if (!keys['L'])
{
lPressed = false;
}
if (keys['B'] && !bPressed)
{
bPressed = true;
blend = !blend;
if (!blend)
{
//glDisable( GL_BLEND );
//glEnable( GL_DEPTH_TEST );
}
else
{
//glEnable( GL_BLEND );
//glDisable( GL_DEPTH_TEST );
}
}
if (!keys['B'])
{
bPressed = false;
}
if (keys['F'] && !fPressed)
{
fPressed = true;
filter += 1;
if (filter > 2)
{
filter = 0;
}
}
if (!keys['F'])
{
fPressed = false;
}
if (keys[VK_PRIOR] && !pgUpPressed)
{
pgUpPressed = true;
lookupdown -= 1.0f;
}
if (!keys[VK_PRIOR])
{
pgUpPressed = false;
}
if (keys[VK_NEXT] && !pgDnPressed)
{
pgDnPressed = true;
lookupdown += 1.0f;
}
if (!keys[VK_NEXT])
{
pgDnPressed = false;
}
if (keys[VK_DOWN])
{
xPos += (float) sin( heading * piover180 ) * 0.0025f; //Move the player on the X-Plane
zPos += (float) sin( heading * piover180 ) * 0.0025f; //Move on the Z plane
if (walkbiasangle <= 1.0f)
{
walkbiasangle = 359.0f;
}
else
{
walkbiasangle -= 10;
}
walkbias = (float) sin( walkbiasangle * piover180) / 20.0f; //Cause the player to bounce
}
if (keys[VK_UP])
{
xPos -= (float) sin( heading * piover180 ) * 0.0025f; //Move the player on the X-Plane
zPos -= (float) sin( heading * piover180 ) * 0.0025f; //Move on the Z plane
if (walkbiasangle >= 359.0f)
{
walkbiasangle = 0.0f;
}
else
{
walkbiasangle += 10;
}
walkbias = (float) sin( walkbiasangle * piover180) / 20.0f; //Cause the player to bounce
}
if (keys[VK_RIGHT])
{
heading -= 0.2f;
yRot -= 0.25f;
}
if (keys[VK_LEFT])
{
heading += 0.2f;
yRot += 0.25f;
}
}
wglDeleteContext(hRC);
ReleaseDC(hWnd, hDC);
}
[/code]
[b]texture.h[/b]
[code]
#ifndef __TEXTURE_H__
#define __TEXTURE_H__
#pragma comment(lib, "Opengl32.lib") //Link to OpenGL32.lib so we can use OpenGL stuff
#include <windows.h> // Standard windows header
#include <stdio.h> // Standard I/O header
#include <gl\gl.h> // Header for OpenGL32 library
typedef struct
{
GLubyte *imageData; //Holds all color-values for the image
GLuint bpp; //Number of bits per pixel
GLuint width; //Width of image
GLuint height; //Height of image
GLuint texID; //Texture ID for use with glBindTexture
GLuint type; //Data stored in *ImageData (GL_RGB or GL_RGBA)
} Texture;
#endif //__TEXTURE_H__[/code]
[b]tga.h[/b]
[code]
#ifndef __TGA_H__
#define __TGA_H__
#pragma comment(lib, "OpenGL32.lib") // Link to the Opengl32.lib
#include <windows.h>
#include <stdio.h>
#include <gl\gl.h>
#include "texture.h"
typedef struct
{
GLubyte Header[12]; //File Header used to determine file type
} TGAHeader;
typedef struct
{
GLubyte header[6]; //Hold the first 6 useful bytes of a header
GLubyte bytesPerPixel; //Number of BYTES per Pixel (3 or 4)
GLubyte imageSize; //Amount of Memory needed to load the image
GLuint type; //Type, GL_RGB or GL_RGBA
GLuint Height; //Height
GLuint Width; //Width
GLuint Bpp; //Number of BITS per Pixel (24 or 32)
} TGA;
TGAHeader tgaheader; //Store our File Header
TGA tga; //Store our TGA Information
//Uncompressed TGA Header
GLubyte uTGAcompare[12] = {0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0};
//Compressed TGA Header
GLubyte cTGAcompare[12] = {0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0};
//Load an Uncompressed File
bool LoadUncompressedTGA( Texture *, char *, FILE *);
//Load a Compressed File
bool LoadCompressedTGA( Texture *, char *, FILE *);
#endif //__TGA_H__[/code]
[b]tga.cpp[/b]
[code]
/********************************************************************************
/Name: TGA.cpp *
/Header: tga.h *
/Purpose: Load Compressed and Uncompressed TGA files *
/Functions: LoadTGA(Texture * texture, char * filename) *
/ LoadCompressedTGA(Texture * texture, char * filename, FILE * fTGA) *
/ LoadUncompressedTGA(Texture * texture, char * filename, FILE * fTGA)*
/*******************************************************************************/
#include "tga.h"
/********************************************************************************
/name : LoadTGA(Texture * texture, char * filename) *
/function: Open and test the file to make sure it is a valid TGA file *
/parems: texture, pointer to a Texture structure *
/ filename, string pointing to file to open *
/********************************************************************************/
bool LoadTGA(Texture * texture, char * filename) // Load a TGA file
{
FILE * fTGA; // File pointer to texture file
fTGA = fopen(filename, "rb"); // Open file for reading
if(fTGA == NULL) // If it didn't open....
{
MessageBoxA(NULL, "Could not open texture file", "TGA_ERROR", MB_OK); // Display an error message
return false; // Exit function
}
if(fread(&tgaheader, sizeof(TGAHeader), 1, fTGA) == 0) // Attempt to read 12 byte header from file
{
MessageBoxA(NULL, "Could not read file header", "TGA_ERROR", MB_OK); // If it fails, display an error message
if(fTGA != NULL) // Check to seeiffile is still open
{
fclose(fTGA); // If it is, close it
}
return false; // Exit function
}
if(memcmp(uTGAcompare, &tgaheader, sizeof(tgaheader)) == 0) // See if header matches the predefined header of
{ // an Uncompressed TGA image
LoadUncompressedTGA(texture, filename, fTGA); // If so, jump to Uncompressed TGA loading code
}
else if(memcmp(cTGAcompare, &tgaheader, sizeof(tgaheader)) == 0) // See if header matches the predefined header of
{ // an RLE compressed TGA image
LoadCompressedTGA(texture, filename, fTGA); // If so, jump to Compressed TGA loading code
}
else // If header matches neither type
{
MessageBoxA(NULL, "TGA file be type 2 or type 10 ", "Invalid Image", MB_OK); // Display an error
fclose(fTGA);
return false; // Exit function
}
return true; // All went well, continue on
}
bool LoadUncompressedTGA(Texture * texture, char * filename, FILE * fTGA) // Load an uncompressed TGA (note, much of this code is based on NeHe's
{ // TGA Loading code nehe.gamedev.net)
if(fread(tga.header, sizeof(tga.header), 1, fTGA) == 0) // Read TGA header
{
MessageBoxA(NULL, "Could not read info header", "TGA_ERROR", MB_OK); // Display error
if(fTGA != NULL) // if file is still open
{
fclose(fTGA); // Close it
}
return false; // Return failular
}
texture->width = tga.header[1] * 256 + tga.header[0]; // Determine The TGA Width (highbyte*256+lowbyte)
texture->height = tga.header[3] * 256 + tga.header[2]; // Determine The TGA Height (highbyte*256+lowbyte)
texture->bpp = tga.header[4]; // Determine the bits per pixel
tga.Width = texture->width; // Copy width into local structure
tga.Height = texture->height; // Copy height into local structure
tga.Bpp = texture->bpp; // Copy BPP into local structure
if((texture->width <= 0) || (texture->height <= 0) || ((texture->bpp != 24) && (texture->bpp !=32))) // Make sure all information is valid
{
MessageBoxA(NULL, "Invalid texture information", "TGA_ERROR", MB_OK); // Display Error
if(fTGA != NULL) // Check if file is still open
{
fclose(fTGA); // If so, close it
}
return false; // Return failed
}
if(texture->bpp == 24) // If the BPP of the image is 24...
texture->type = GL_RGB; // Set Image type to GL_RGB
else // Else if its 32 BPP
texture->type = GL_RGBA; // Set image type to GL_RGBA
tga.bytesPerPixel = (tga.Bpp / 8); // Compute the number of BYTES per pixel
tga.imageSize = (tga.bytesPerPixel * tga.Width * tga.Height); // Compute the total amout ofmemory needed to store data
texture->imageData = (GLubyte *)malloc(tga.imageSize); // Allocate that much memory
if(texture->imageData == NULL) // If no space was allocated
{
MessageBoxA(NULL, "Could not allocate memory for image", "TGA_ERROR", MB_OK); // Display Error
fclose(fTGA); // Close the file
return false; // Return failed
}
if(fread(texture->imageData, 1, tga.imageSize, fTGA) != tga.imageSize) // Attempt to read image data
{
MessageBoxA(NULL, "Could not read image data", "TGA_ERROR", MB_OK); // Display Error
if(texture->imageData != NULL) // If imagedata has data in it
{
free(texture->imageData); // Delete data from memory
}
fclose(fTGA); // Close file
return false; // Return failed
}
// Byte Swapping Optimized By Steve Thomas
for(GLuint cswap = 0; cswap < (int)tga.imageSize; cswap += tga.bytesPerPixel)
{
texture->imageData[cswap] ^= texture->imageData[cswap+2] ^=
texture->imageData[cswap] ^= texture->imageData[cswap+2];
}
fclose(fTGA); // Close file
return true; // Return success
}
bool LoadCompressedTGA(Texture * texture, char * filename, FILE * fTGA) // Load COMPRESSED TGAs
{
if(fread(tga.header, sizeof(tga.header), 1, fTGA) == 0) // Attempt to read header
{
MessageBoxA(NULL, "Could not read info header", "TGA_ERROR", MB_OK); // Display Error
if(fTGA != NULL) // If file is open
{
fclose(fTGA); // Close it
}
return false; // Return failed
}
texture->width = tga.header[1] * 256 + tga.header[0]; // Determine The TGA Width (highbyte*256+lowbyte)
texture->height = tga.header[3] * 256 + tga.header[2]; // Determine The TGA Height (highbyte*256+lowbyte)
texture->bpp = tga.header[4]; // Determine Bits Per Pixel
tga.Width = texture->width; // Copy width to local structure
tga.Height = texture->height; // Copy width to local structure
tga.Bpp = texture->bpp; // Copy width to local structure
if((texture->width <= 0) || (texture->height <= 0) || ((texture->bpp != 24) && (texture->bpp !=32))) //Make sure all texture info is ok
{
MessageBoxA(NULL, "Invalid texture information", "TGA_ERROR", MB_OK); // If it isnt...Display error
if(fTGA != NULL) // Check if file is open
{
fclose(fTGA); // Ifit is, close it
}
return false; // Return failed
}
if(texture->bpp == 24) // If the BPP of the image is 24...
texture->type = GL_RGB; // Set Image type to GL_RGB
else // Else if its 32 BPP
texture->type = GL_RGBA; // Set image type to GL_RGBA
tga.bytesPerPixel = (tga.Bpp / 8); // Compute BYTES per pixel
tga.imageSize = (tga.bytesPerPixel * tga.Width * tga.Height); // Compute amout of memory needed to store image
texture->imageData = (GLubyte *)malloc(tga.imageSize); // Allocate that much memory
if(texture->imageData == NULL) // If it wasnt allocated correctly..
{
MessageBoxA(NULL, "Could not allocate memory for image", "TGA_ERROR", MB_OK); // Display Error
fclose(fTGA); // Close file
return false; // Return failed
}
GLuint pixelcount = tga.Height * tga.Width; // Nuber of pixels in the image
GLuint currentpixel = 0; // Current pixel being read
GLuint currentbyte = 0; // Current byte
GLubyte * colorbuffer = (GLubyte *)malloc(tga.bytesPerPixel); // Storage for 1 pixel
do
{
GLubyte chunkheader = 0; // Storage for "chunk" header
if(fread(&chunkheader, sizeof(GLubyte), 1, fTGA) == 0) // Read in the 1 byte header
{
MessageBoxA(NULL, "Could not read RLE header", "TGA_ERROR", MB_OK); // Display Error
if(fTGA != NULL) // If file is open
{
fclose(fTGA); // Close file
}
if(texture->imageData != NULL) // If there is stored image data
{
free(texture->imageData); // Delete image data
}
return false; // Return failed
}
if(chunkheader < 128) // If the ehader is < 128, it means the that is the number of RAW color packets minus 1
{ // that follow the header
chunkheader++; // add 1 to get number of following color values
for(short counter = 0; counter < chunkheader; counter++) // Read RAW color values
{
if(fread(colorbuffer, 1, tga.bytesPerPixel, fTGA) != tga.bytesPerPixel) // Try to read 1 pixel
{
MessageBoxA(NULL, "Could not read image data", "TGA_ERROR", MB_OK); // IF we cant, display an error
if(fTGA != NULL) // See if file is open
{
fclose(fTGA); // If so, close file
}
if(colorbuffer != NULL) // See if colorbuffer has data in it
{
free(colorbuffer); // If so, delete it
}
if(texture->imageData != NULL) // See if there is stored Image data
{
free(texture->imageData); // If so, delete it too
}
return false; // Return failed
}
// write to memory
texture->imageData[currentbyte ] = colorbuffer[2]; // Flip R and B vcolor values around in the process
texture->imageData[currentbyte + 1 ] = colorbuffer[1];
texture->imageData[currentbyte + 2 ] = colorbuffer[0];
if(tga.bytesPerPixel == 4) // if its a 32 bpp image
{
texture->imageData[currentbyte + 3] = colorbuffer[3]; // copy the 4th byte
}
currentbyte += tga.bytesPerPixel; // Increase thecurrent byte by the number of bytes per pixel
currentpixel++; // Increase current pixel by 1
if(currentpixel > pixelcount) // Make sure we havent read too many pixels
{
MessageBoxA(NULL, "Too many pixels read", "TGA_ERROR", NULL); // if there is too many... Display an error!
if(fTGA != NULL) // If there is a file open
{
fclose(fTGA); // Close file
}
if(colorbuffer != NULL) // If there is data in colorbuffer
{
free(colorbuffer); // Delete it
}
if(texture->imageData != NULL) // If there is Image data
{
free(texture->imageData); // delete it
}
return false; // Return failed
}
}
}
else // chunkheader > 128 RLE data, next color reapeated chunkheader - 127 times
{
chunkheader -= 127; // Subteact 127 to get rid of the ID bit
if(fread(colorbuffer, 1, tga.bytesPerPixel, fTGA) != tga.bytesPerPixel) // Attempt to read following color values
{
MessageBoxA(NULL, "Could not read from file", "TGA_ERROR", MB_OK); // If attempt fails.. Display error (again)
if(fTGA != NULL) // If thereis a file open
{
fclose(fTGA); // Close it
}
if(colorbuffer != NULL) // If there is data in the colorbuffer
{
free(colorbuffer); // delete it
}
if(texture->imageData != NULL) // If thereis image data
{
free(texture->imageData); // delete it
}
return false; // return failed
}
for(short counter = 0; counter < chunkheader; counter++) // copy the color into the image data as many times as dictated
{ // by the header
texture->imageData[currentbyte ] = colorbuffer[2]; // switch R and B bytes areound while copying
texture->imageData[currentbyte + 1 ] = colorbuffer[1];
texture->imageData[currentbyte + 2 ] = colorbuffer[0];
if(tga.bytesPerPixel == 4) // If TGA images is 32 bpp
{
texture->imageData[currentbyte + 3] = colorbuffer[3]; // Copy 4th byte
}
currentbyte += tga.bytesPerPixel; // Increase current byte by the number of bytes per pixel
currentpixel++; // Increase pixel count by 1
if(currentpixel > pixelcount) // Make sure we havent written too many pixels
{
MessageBoxA(NULL, "Too many pixels read", "TGA_ERROR", NULL); // if there is too many... Display an error!
if(fTGA != NULL) // If there is a file open
{
fclose(fTGA); // Close file
}
if(colorbuffer != NULL) // If there is data in colorbuffer
{
free(colorbuffer); // Delete it
}
if(texture->imageData != NULL) // If there is Image data
{
free(texture->imageData); // delete it
}
return false; // Return failed
}
}
}
}
while(currentpixel < pixelcount); // Loop while there are still pixels left
fclose(fTGA); // Close the file
return true; // return success
}
[/code]
Again, it compiles fine but calling glBindTexture( GL_TEXTURE_2D, <textureID> ) before drawing my Triangles doesn't make them show up in anything but grey.
Also if I use the commented code (~280 in sample.cpp) it still shows up as grey, even though it came from the example and works in the example's EXE. (I didn't recompile the example)
I'm probably missing something obivous here...
Haven't personally used deprecated OpenGL stuff, but it would be a good idea to step through the code with your favorite at debugger the following points (just work backwards from the most pertinent API calls):
[code] glTexCoord2f( u_m, v_m);
glVertex3f( x_m, y_m, z_m );
[/code]
Ensure u_m and v_m vary from 0.f to 1.f
If they do, make sure they make [b]sense[/b]; you definitely want to rule out a fault with the API or your configuration of the API. Yes, you'll have to compare vertex coordinates to UV coordinates. Total pain in the ass but can save a lot of time. Depending on how mundane this task is, I sometimes leave this to the end. Consider using geometry consisting of only one face with stupid-easy coordinates.
Also step through here:
[code]glTexImage2D( GL_TEXTURE_2D, 0, texture[loop].bpp / 8, texture[loop].width, texture[loop].height, 0, texture[loop].type, GL_UNSIGNED_BYTE, texture[loop].imageData );[/code]
Ensure imageData is not all '0's or 'F's, etc.
Again, make sure the values make sense. You should [i]really[/i] review the reference to make sure you're setting the not-so-obvious fields correctly. Some enumerations are named very similarly to others but are completely unrelated.
Know what? Screw it, check the obvious fields too.
If these are correct, then a setting might not be set correctly or OpenGL may not have been configured correctly. I've noticed that you don't call glGetError() at all. You may want to try writing a method/macro that will just throw an exception if this doesn't return 0. Don't forget to call glGetError() before the method you're doing error checking for to clear the error status.
If you were writing non-deprecated code, I'd check to make sure the bind locations of shader attributes/whatever were non-zero to indicate that they are, indeed, being used. ...misspelling or miss-capitalizing shader variables... :smithicide:
If you've already done this, then you'll probably have found the answer by the time you read this :v:
imageData showed up as like "173F" with a funky F in the debugger.
Would it be easier for me to just learn not deprecated code? Most of the OpenGL tutorials I can find are years old.
You're calling LoadGlTextures() before running the rest of the GL initialization routine -- with GL_TEXTURE_2D still disabled. Enable GL_TEXTURE_2D before trying to bind it and load a texture.
[QUOTE=Lord Ned;29657747]Would it be easier for me to just learn not deprecated code? Most of the OpenGL tutorials I can find are years old.[/QUOTE]
You really should learn modern OpenGL. There might be a little more boilerplate for simple applications, but its approach really is cleaner and more consistent than the old fixed-function pipeline.
Sorry, you need to Log In to post a reply to this thread.