Link Errors, Oh how I loathe them ...

Started by
1 comment, last by Zmurf 18 years ago
I just added a 3ds and texture loading class to my game. However I am now getting the following error link error.
Quote:Game error LNK2019: unresolved external symbol _auxDIBImageLoadA@4 referenced in function "public: void __thiscall GLTexture::LoadBMP(char *)" (?LoadBMP@GLTexture@@QAEXPAD@Z)
And here are the files that the link error is comming from. GLTexture.h
//////////////////////////////////////////////////////////////////////
//
// OpenGL Texture Class
// by: Matthew Fairfax
//
// GLTexture.h: interface for the GLTexture class.
// This class loads a texture file and prepares it
// to be used in OpenGL. It can open a bitmap or a
// targa file. The min filter is set to mipmap b/c
// they look better and the performance cost on
// modern video cards in negligible. I leave all of
// the texture management to the application. I have
// included the ability to load the texture from a
// Visual Studio resource. The bitmap's id must be
// be surrounded by quotation marks (i.e. "Texture.bmp").
// The targa files must be in a resource type of "TGA"
// (including the quotes). The targa's id must be
// surrounded by quotation marks (i.e. "Texture.tga").
//
// Usage:
// GLTexture tex;
// GLTexture tex1;
// GLTexture tex3;
//
// tex.Load("texture.bmp"); // Loads a bitmap
// tex.Use();				// Binds the bitmap for use
// 
// tex1.LoadFromResource("texture.tga"); // Loads a targa
// tex1.Use();				 // Binds the targa for use
//
// // You can also build a texture with a single color and use it
// tex3.BuildColorTexture(255, 0, 0);	// Builds a solid red texture
// tex3.Use();				 // Binds the targa for use
//
//////////////////////////////////////////////////////////////////////

#ifndef GLTEXTURE_H
#define GLTEXTURE_H

#include <windows.h>		// Header File For Windows
#include <gl\gl.h>			// Header File For The OpenGL32 Library
#include <gl\glu.h>			// Header File For The GLu32 Library
#include <gl\glaux.h>		// Header File For The Glaux Library

class GLTexture  
{
public:
	char *texturename;								// The textures name
	unsigned int texture[1];						// OpenGL's number for the texture
	int width;										// Texture's width
	int height;										// Texture's height
	void Use();										// Binds the texture for use
	void BuildColorTexture(unsigned char r, unsigned char g, unsigned char b);	// Sometimes we want a texture of uniform color
	void LoadTGAResource(char *name);				// Load a targa from the resources
	void LoadBMPResource(char *name);				// Load a bitmap from the resources
	void LoadFromResource(char *name);				// Load the texture from a resource
	void LoadTGA(char *name);						// Loads a targa file
	void LoadBMP(char *name);						// Loads a bitmap file
	void Load(char *name);							// Load the texture
	GLTexture();									// Constructor
	virtual ~GLTexture();							// Destructor

};

#endif GLTEXTURE_H

GLTexture.cpp
//////////////////////////////////////////////////////////////////////
//
// OpenGL Texture Class
// by: Matthew Fairfax
//
// GLTexture.cpp: implementation of the GLTexture class.
// This class loads a texture file and prepares it
// to be used in OpenGL. It can open a bitmap or a
// targa file. The min filter is set to mipmap b/c
// they look better and the performance cost on
// modern video cards in negligible. I leave all of
// the texture management to the application. I have
// included the ability to load the texture from a
// Visual Studio resource. The bitmap's id must be
// be surrounded by quotation marks (i.e. "Texture.bmp").
// The targa files must be in a resource type of "TGA"
// (including the quotes). The targa's id must be
// surrounded by quotation marks (i.e. "Texture.tga").
//
// Usage:
// GLTexture tex;
// GLTexture tex1;
// GLTexture tex3;
//
// tex.Load("texture.bmp"); // Loads a bitmap
// tex.Use();				// Binds the bitmap for use
// 
// tex1.LoadFromResource("texture.tga"); // Loads a targa
// tex1.Use();				 // Binds the targa for use
//
// // You can also build a texture with a single color and use it
// tex3.BuildColorTexture(255, 0, 0);	// Builds a solid red texture
// tex3.Use();				 // Binds the targa for use
//
//////////////////////////////////////////////////////////////////////

#include "GLTexture.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

GLTexture::GLTexture()
{

}

GLTexture::~GLTexture()
{

}

void GLTexture::Load(char *name)
{
	// make the texture name all lower case
	texturename = strlwr(strdup(name));

	// strip "'s
	if (strstr(texturename, "\""))
		texturename = strtok(texturename, "\"");

	// check the file extension to see what type of texture
	if(strstr(texturename, ".bmp"))	
		LoadBMP(texturename);
	if(strstr(texturename, ".tga"))	
		LoadTGA(texturename);
}

void GLTexture::LoadFromResource(char *name)
{
	// make the texture name all lower case
	texturename = strlwr(strdup(name));

	// check the file extension to see what type of texture
	if(strstr(texturename, ".bmp"))
		LoadBMPResource(name);
	if(strstr(texturename, ".tga"))	
		LoadTGAResource(name);
}

void GLTexture::Use()
{
	glEnable(GL_TEXTURE_2D);								// Enable texture mapping
	glBindTexture(GL_TEXTURE_2D, texture[0]);				// Bind the texture as the current one
}

void GLTexture::LoadBMP(char *name)
{
	// Create a place to store the texture
	AUX_RGBImageRec *TextureImage[1];

	// Set the pointer to NULL
	memset(TextureImage,0,sizeof(void *)*1);

	// Load the bitmap and assign our pointer to it
	TextureImage[0] = auxDIBImageLoad(name);

	// Just in case we want to use the width and height later
	width = TextureImage[0]->sizeX;
	height = TextureImage[0]->sizeY;

	// Generate the OpenGL texture id
	glGenTextures(1, &texture[0]);

	// Bind this texture to its id
	glBindTexture(GL_TEXTURE_2D, texture[0]);

	// Use mipmapping filter
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

	// Generate the mipmaps
	gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);

	// Cleanup
	if (TextureImage[0])
	{
		if (TextureImage[0]->data)
			free(TextureImage[0]->data);

		free(TextureImage[0]);
	}
}

void GLTexture::LoadTGA(char *name)
{
	GLubyte		TGAheader[12]	= {0,0,2,0,0,0,0,0,0,0,0,0};// Uncompressed TGA header
	GLubyte		TGAcompare[12];								// Used to compare TGA header
	GLubyte		header[6];									// First 6 useful bytes of the header
	GLuint		bytesPerPixel;								// Holds the number of bytes per pixel used
	GLuint		imageSize;									// Used to store the image size
	GLuint		temp;										// Temporary variable
	GLuint		type			= GL_RGBA;					// Set the default type to RBGA (32 BPP)
	GLubyte		*imageData;									// Image data (up to 32 Bits)
	GLuint		bpp;										// Image color depth in bits per pixel.

	FILE *file = fopen(name, "rb");							// Open the TGA file

	// Load the file and perform checks
	if(file == NULL ||														// Does file exist?
	   fread(TGAcompare,1,sizeof(TGAcompare),file) != sizeof(TGAcompare) ||	// Are there 12 bytes to read?
	   memcmp(TGAheader,TGAcompare,sizeof(TGAheader)) != 0				 ||	// Is it the right format?
	   fread(header,1,sizeof(header),file) != sizeof(header))				// If so then read the next 6 header bytes
	{
		if (file == NULL)									// If the file didn't exist then return
			return;
		else
		{
			fclose(file);									// If something broke then close the file and return
			return;
		}
	}

	// Determine the TGA width and height (highbyte*256+lowbyte)
	width  = header[1] * 256 + header[0];
	height = header[3] * 256 + header[2];
    
	// Check to make sure the targa is valid and is 24 bit or 32 bit
	if(width	<=0	||										// Is the width less than or equal to zero
	   height	<=0	||										// Is the height less than or equal to zero
	   (header[4] != 24 && header[4] != 32))				// Is it 24 or 32 bit?
	{
		fclose(file);										// If anything didn't check out then close the file and return
		return;
	}

	bpp				= header[4];							// Grab the bits per pixel
	bytesPerPixel	= bpp / 8;								// Divide by 8 to get the bytes per pixel
	imageSize		= width * height * bytesPerPixel;		// Calculate the memory required for the data

	// Allocate the memory for the image data
	imageData		= new GLubyte[imageSize];

	// Make sure the data is allocated write and load it
	if(imageData == NULL ||									// Does the memory storage exist?
	   fread(imageData, 1, imageSize, file) != imageSize)	// Does the image size match the memory reserved?
	{
		if(imageData != NULL)								// Was the image data loaded
			free(imageData);								// If so, then release the image data

		fclose(file);										// Close the file
		return;
	}

	// Loop through the image data and swap the 1st and 3rd bytes (red and blue)
	for(GLuint i = 0; i < int(imageSize); i += bytesPerPixel)
	{
		temp = imageData;
		imageData = imageData;
		imageData = temp;
	}

	<span class="cpp-comment">// We are done with the file so close it</span>
	fclose(file);

	<span class="cpp-comment">// Set the type</span>
	<span class="cpp-keyword">if</span> (bpp == <span class="cpp-number">24</span>)
		type = GL_RGB;
	
	<span class="cpp-comment">// Generate the OpenGL texture id</span>
	glGenTextures(<span class="cpp-number">1</span>, &amp;texture[<span class="cpp-number">0</span>]);

	<span class="cpp-comment">// Bind this texture to its id</span>
	glBindTexture(GL_TEXTURE_2D, texture[<span class="cpp-number">0</span>]);

	<span class="cpp-comment">// Use mipmapping filter</span>
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

	<span class="cpp-comment">// Generate the mipmaps</span>
	gluBuild2DMipmaps(GL_TEXTURE_2D, type, width, height, type, GL_UNSIGNED_BYTE, imageData);

	<span class="cpp-comment">// Cleanup</span>
	free(imageData);
}


<span class="cpp-keyword">void</span> GLTexture::LoadBMPResource(<span class="cpp-keyword">char</span> *name)
{
	<span class="cpp-comment">// Find the bitmap in the bitmap resources</span>
	HRSRC hrsrc = FindResource(<span class="cpp-number">0</span>, name, RT_BITMAP);

	<span class="cpp-comment">// If you can't find it then return</span>
	<span class="cpp-keyword">if</span> (hrsrc==<span class="cpp-number">0</span>)
		<span class="cpp-keyword">return</span>;

	<span class="cpp-comment">// Load the bitmap</span>
	HGLOBAL resource = LoadResource(<span class="cpp-number">0</span>, hrsrc);
	
	<span class="cpp-comment">// If you can't load it then return</span>
	<span class="cpp-keyword">if</span> (resource==<span class="cpp-number">0</span>)
		<span class="cpp-keyword">return</span>;

	<span class="cpp-comment">// Load it into the buffer</span>
	<span class="cpp-keyword">void</span> *buffer = LockResource(resource);

	<span class="cpp-comment">// Cast it into a bitmap</span>
	BITMAP *bmp = (BITMAP*)buffer;

	<span class="cpp-comment">// Get the height and width for future use</span>
	width = bmp-&gt;bmWidth;
	height = bmp-&gt;bmHeight;

	<span class="cpp-comment">// Reverse the blue colot bit and the red color bit</span>
	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> *ptr = (<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> *)buffer+<span class="cpp-keyword">sizeof</span>(BITMAPINFO)+<span class="cpp-number">2</span>;
	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> temp;

	<span class="cpp-keyword">for</span> (<span class="cpp-keyword">int</span> i = <span class="cpp-number">0</span>; i &lt; width*height; i++)
	{
		temp = ptr[i*<span class="cpp-number">3</span>];
		ptr[i*<span class="cpp-number">3</span>] = ptr[i*<span class="cpp-number">3</span>+<span class="cpp-number">2</span>];
		ptr[i*<span class="cpp-number">3</span>+<span class="cpp-number">2</span>] = temp;
	}

	<span class="cpp-comment">// Generate the OpenGL texture id</span>
	glGenTextures(<span class="cpp-number">1</span>, &amp;texture[<span class="cpp-number">0</span>]);

	<span class="cpp-comment">// Bind this texture to its id</span>
	glBindTexture(GL_TEXTURE_2D, texture[<span class="cpp-number">0</span>]);

	<span class="cpp-comment">// Use mipmapping filter</span>
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

	<span class="cpp-comment">// Generate the mipmaps</span>
	gluBuild2DMipmaps(GL_TEXTURE_2D, <span class="cpp-number">3</span>, width, height, GL_RGB, GL_UNSIGNED_BYTE, (<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> *)buffer+<span class="cpp-keyword">sizeof</span>(BITMAPINFO)+<span class="cpp-number">2</span>);
	<span class="cpp-comment">//gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, bmp-&gt;bmBits);</span>

	<span class="cpp-comment">// Cleanup</span>
	free(buffer);
	free(bmp);
}

<span class="cpp-keyword">void</span> GLTexture::LoadTGAResource(<span class="cpp-keyword">char</span> *name)
{
	<span class="cpp-comment">// struct to cast the resource into</span>
	<span class="cpp-keyword">struct</span> TGAstruct {
		GLubyte	TGAcompare[<span class="cpp-number">12</span>];								<span class="cpp-comment">// Used to compare TGA header</span>
		GLubyte	header[<span class="cpp-number">6</span>];									<span class="cpp-comment">// First 6 useful bytes of the header</span>
	};

	GLubyte		TGAheader[<span class="cpp-number">12</span>]	= {<span class="cpp-number">0</span>,<span class="cpp-number">0</span>,<span class="cpp-number">2</span>,<span class="cpp-number">0</span>,<span class="cpp-number">0</span>,<span class="cpp-number">0</span>,<span class="cpp-number">0</span>,<span class="cpp-number">0</span>,<span class="cpp-number">0</span>,<span class="cpp-number">0</span>,<span class="cpp-number">0</span>,<span class="cpp-number">0</span>};<span class="cpp-comment">// Uncompressed TGA header</span>
	GLuint		bytesPerPixel;								<span class="cpp-comment">// Holds the number of bytes per pixel used</span>
	GLuint		imageSize;									<span class="cpp-comment">// Used to store the image size</span>
	GLuint		temp;										<span class="cpp-comment">// Temporary variable</span>
	GLuint		type			= GL_RGBA;					<span class="cpp-comment">// Set the default type to RBGA (32 BPP)</span>
	GLubyte		*imageData;									<span class="cpp-comment">// Image data (up to 32 Bits)</span>
	GLuint		bpp;										<span class="cpp-comment">// Image color depth in bits per pixel.</span>

	<span class="cpp-comment">// Find the targa in the "TGA" resources</span>
	HRSRC hrsrc = FindResource(<span class="cpp-number">0</span>, name, <span class="cpp-literal">"TGA"</span>);

	<span class="cpp-comment">// If you can't find it then return</span>
	<span class="cpp-keyword">if</span> (hrsrc==<span class="cpp-number">0</span>)
		<span class="cpp-keyword">return</span>;

	<span class="cpp-comment">// Load the targa</span>
	HGLOBAL resource = LoadResource(<span class="cpp-number">0</span>, hrsrc);

	<span class="cpp-comment">// If you can't load it then return</span>
	<span class="cpp-keyword">if</span> (resource==<span class="cpp-number">0</span>)
		<span class="cpp-keyword">return</span>;

	<span class="cpp-comment">// Load it into the buffer</span>
	<span class="cpp-keyword">void</span> *buffer = LockResource(resource);

	<span class="cpp-comment">// Cast it into the targa struct</span>
	TGAstruct *top = (TGAstruct*)buffer;

	<span class="cpp-comment">// Make sure it checks out against our comparison header</span>
	<span class="cpp-keyword">if</span> (memcmp(TGAheader,top,<span class="cpp-keyword">sizeof</span>(TGAheader)) != <span class="cpp-number">0</span>)
		<span class="cpp-keyword">return</span>;

	<span class="cpp-comment">// Determine the TGA width and height (highbyte*256+lowbyte)</span>
	width  = top-&gt;header[<span class="cpp-number">1</span>] * <span class="cpp-number">256</span> + top-&gt;header[<span class="cpp-number">0</span>];
	height = top-&gt;header[<span class="cpp-number">3</span>] * <span class="cpp-number">256</span> + top-&gt;header[<span class="cpp-number">2</span>];
    
	<span class="cpp-comment">// Check to make sure the targa is valid and is 24 bit or 32 bit</span>
	<span class="cpp-keyword">if</span>(width	&lt;=<span class="cpp-number">0</span>	||										<span class="cpp-comment">// Is the width less than or equal to zero</span>
	   height	&lt;=<span class="cpp-number">0</span>	||										<span class="cpp-comment">// Is the height less than or equal to zero</span>
	   (top-&gt;header[<span class="cpp-number">4</span>] != <span class="cpp-number">24</span> &amp;&amp; top-&gt;header[<span class="cpp-number">4</span>] != <span class="cpp-number">32</span>))		<span class="cpp-comment">// Is it 24 or 32 bit?</span>
	{
		<span class="cpp-comment">// If anything didn't check out then close the file and return</span>
		<span class="cpp-keyword">return</span>;
	}

	bpp				= top-&gt;header[<span class="cpp-number">4</span>];							<span class="cpp-comment">// Grab the bits per pixel</span>
	bytesPerPixel	= bpp / <span class="cpp-number">8</span>;								<span class="cpp-comment">// Divide by 8 to get the bytes per pixel</span>
	imageSize		= width * height * bytesPerPixel;		<span class="cpp-comment">// Calculate the memory required for the data</span>

	<span class="cpp-comment">// Allocate the memory for the image data</span>
	imageData		= <span class="cpp-keyword">new</span> GLubyte[imageSize];

	<span class="cpp-comment">// Load the data in</span>
	memcpy(imageData, (GLubyte*)buffer+<span class="cpp-number">18</span>, imageSize);

	<span class="cpp-comment">// Loop through the image data and swap the 1st and 3rd bytes (red and blue)</span>
	<span class="cpp-keyword">for</span>(GLuint i = <span class="cpp-number">0</span>; i &lt; <span class="cpp-keyword">int</span>(imageSize); i += bytesPerPixel)
	{
		temp = imageData<span style="font-weight:bold;">;
		imageData<span style="font-weight:bold;"> = imageData;
		imageData = temp;
	}

	<span class="cpp-comment">// Set the type</span>
	<span class="cpp-keyword">if</span> (bpp == <span class="cpp-number">24</span>)
		type = GL_RGB;
	
	<span class="cpp-comment">// Generate the OpenGL texture id</span>
	glGenTextures(<span class="cpp-number">1</span>, &amp;texture[<span class="cpp-number">0</span>]);

	<span class="cpp-comment">// Bind this texture to its id</span>
	glBindTexture(GL_TEXTURE_2D, texture[<span class="cpp-number">0</span>]);

	<span class="cpp-comment">// Use mipmapping filter</span>
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

	<span class="cpp-comment">// Generate the mipmaps</span>
	gluBuild2DMipmaps(GL_TEXTURE_2D, type, width, height, type, GL_UNSIGNED_BYTE, imageData);

	<span class="cpp-comment">// Cleanup</span>
	free(imageData);
	free(buffer);
	free(top);
}

<span class="cpp-keyword">void</span> GLTexture::BuildColorTexture(<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> r, <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> g, <span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> b)
{
	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">char</span> data[<span class="cpp-number">12</span>];	<span class="cpp-comment">// a 2x2 texture at 24 bits</span>

	<span class="cpp-comment">// Store the data</span>
	<span class="cpp-keyword">for</span>(<span class="cpp-keyword">int</span> i = <span class="cpp-number">0</span>; i &lt; <span class="cpp-number">12</span>; i += <span class="cpp-number">3</span>)
	{
		data<span style="font-weight:bold;"> = r;
		data[i+<span class="cpp-number">1</span>] = g;
		data[i+<span class="cpp-number">2</span>] = b;
	}

	<span class="cpp-comment">// Generate the OpenGL texture id</span>
	glGenTextures(<span class="cpp-number">1</span>, &amp;texture[<span class="cpp-number">0</span>]);

	<span class="cpp-comment">// Bind this texture to its id</span>
	glBindTexture(GL_TEXTURE_2D, texture[<span class="cpp-number">0</span>]);

	glPixelStorei(GL_UNPACK_ALIGNMENT, <span class="cpp-number">1</span>);

	<span class="cpp-comment">// Use mipmapping filter</span>
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

	<span class="cpp-comment">// Generate the texture</span>
	gluBuild2DMipmaps(GL_TEXTURE_2D, <span class="cpp-number">3</span>, <span class="cpp-number">2</span>, <span class="cpp-number">2</span>, GL_RGB, GL_UNSIGNED_BYTE, data);
}


</pre></div><!–ENDSCRIPT–>

Thank you very much to anyone who can help!
If it's possible for us to conceive it, than it must be possible.
Advertisement
Open your project settings, look in the Linker area, and make sure that the appropriate .lib file is added for auxDIBImageLoad(). (The file is, IIRC, glaux.lib).

The specific steps to do this depend on your version of Visual Studio.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Thankyou very much!
If it's possible for us to conceive it, than it must be possible.

This topic is closed to new replies.

Advertisement