void settler_ranged_attack_system::on_message(const settler_ranged_attack_message &msg) {
    auto attacker = entity(msg.attacker);
    auto defender = entity(msg.victim);
    if (!attacker || !defender) return;
    auto attacker_stats = attacker->component<game_stats_t>();
    auto attacker_pos = attacker->component<position_t>();
    auto defender_pos = defender->component<position_t>();

    civ_dislike_attacker(defender);

    std::size_t weapon_id, ammo_id;
    std::tie(weapon_id, ammo_id) = get_ranged_and_ammo_id(msg.attacker);
    std::string weapon_name = "fists";
    int weapon_n = 1;
    int weapon_d = 4;
    int weapon_mod = 0;
    if (weapon_id != 0) {
        auto weapon_component = entity(weapon_id)->component<item_t>();
        if (weapon_component) {
            auto weapon_finder = item_defs.find(weapon_component->item_tag);
            if (weapon_finder != item_defs.end()) {
                weapon_name = weapon_finder->second.name;
            }
        }
    }
    if (ammo_id != 0) {
        auto ammo_component = entity(ammo_id)->component<item_t>();
        if (ammo_component) {
            auto ammo_finder = item_defs.find(ammo_component->item_tag);
            if (ammo_finder != item_defs.end()) {
                weapon_n = ammo_finder->second.damage_n;
                weapon_d = ammo_finder->second.damage_d + get_material(ammo_component->material)->damage_bonus;
                weapon_mod = ammo_finder->second.damage_mod;
            }
            --ammo_component->stack_size;
            if (ammo_component->stack_size < 1) delete_entity(ammo_id);
        }
        emit(emit_particles_message{3, attacker_pos->x, attacker_pos->y, attacker_pos->z,
                                    defender_pos->x, defender_pos->y, defender_pos->z});
    }

    LOG ss;
    ss.settler_name(msg.attacker)->text(" attacks ")->other_name(msg.victim)->text(" with their ")->col(rltk::colors::YELLOW)->text(weapon_name+std::string(". "))->col(rltk::colors::WHITE);
    const int skill_modifier = get_skill_modifier(*attacker_stats, "Ranged Attacks");
    const int die_roll = rng.roll_dice(1, 20) + stat_modifier(attacker_stats->dexterity + skill_modifier);
    const int armor_class = calculate_armor_class(*defender);
    if (die_roll > armor_class) {
        const int damage = std::max(1, rng.roll_dice(weapon_n, weapon_d) + weapon_mod + stat_modifier(attacker_stats->strength) + skill_modifier);
        ss.text("The attack hits for "+std::to_string(damage)+" points of damage.");
        emit(inflict_damage_message{ msg.victim, damage, weapon_name });
        gain_skill_from_success(msg.attacker, *attacker_stats, "Ranged Attacks", armor_class, rng);
    } else {
        ss.text("The attack misses.");
    }
    emit_deferred(log_message{ss.chars});
}
示例#2
0
static void *thread(void *arg)
{
	while(1)
	{
		LOG *log = (LOG *)arg;
		sem_wait(&log->sem);
		printf("log->write()\n");
		log->write();
	}
}
示例#3
0
///////////////////BSP::LoadVertices////////
////////////////////////////////////////////
bool BSP::LoadVertices(FILE * file)
{
	//calculate number of vertices
	numVertices=header.directoryEntries[bspVertices].length/sizeof(BSP_LOAD_VERTEX);

	//Create space for this many BSP_LOAD_VERTICES
	BSP_LOAD_VERTEX * loadVertices=new BSP_LOAD_VERTEX[numVertices];
	if(!loadVertices)
	{
		errorLog.OutputError("Unable to allocate memory for %d BSP_LOAD_VERTEXes", numVertices);
		return false;
	}

	//go to vertices in file
	fseek(file, header.directoryEntries[bspVertices].offset, SEEK_SET);

	//read in the vertices
	fread(loadVertices, header.directoryEntries[bspVertices].length, 1, file);

	//Convert to BSP_VERTEXes
	vertices=new BSP_VERTEX[numVertices];
	if(!vertices)
	{
		errorLog.OutputError("Unable to allocate memory for vertices");
		return false;
	}

	for(int i=0; i<numVertices; ++i)
	{
		//swap y and z and negate z
		vertices[i].position.x=loadVertices[i].position.x;
		vertices[i].position.y=loadVertices[i].position.z;
		vertices[i].position.z=-loadVertices[i].position.y;

		//scale down
		vertices[i].position/=64;

		//Transfer texture coordinates (Invert t)
		vertices[i].decalS=loadVertices[i].decalS;
		vertices[i].decalT=-loadVertices[i].decalT;

		//Transfer lightmap coordinates
		vertices[i].lightmapS=loadVertices[i].lightmapS;
		vertices[i].lightmapT=loadVertices[i].lightmapT;
	}

	if(loadVertices)
		delete [] loadVertices;
	loadVertices=NULL;

	return true;
}
示例#4
0
//Load - load a texture from a file
bool IMAGE::Load(char * filename)
{
	//Clear the data if already used
	if(data)
		delete [] data;
	data=NULL;
	bpp=0;
	width=0;
	height=0;
	format=0;

	int filenameLength=strlen(filename);

	if(	strncmp((filename+filenameLength-3), "BMP", 3)==0 ||
		strncmp((filename+filenameLength-3), "bmp", 3)==0)
		return LoadBMP(filename);
	
	if(	strncmp((filename+filenameLength-3), "PCX", 3)==0 ||
		strncmp((filename+filenameLength-3), "pcx", 3)==0)
		return LoadPCX(filename);
	
	if(	strncmp((filename+filenameLength-3), "TGA", 3)==0 ||
		strncmp((filename+filenameLength-3), "tga", 3)==0)
		return LoadTGA(filename);

	errorLog.OutputError("%s does not end in \".tga\", \".bmp\" or \"pcx\"", filename);
	return false;
}
示例#5
0
//Set up variables
bool DemoInit()
{
    if(!window.Init("Project Template", 640, 480, 32, 24, 8, WINDOWED_SCREEN))
        return 0;											//quit if not created

    SetUpARB_multitexture();
    SetUpEXT_texture3D();
    SetUpEXT_texture_edge_clamp();
    SetUpNV_register_combiners();
    SetUpNV_texture_shader();
    SetUpNV_vertex_program();

    if(	!EXT_texture_edge_clamp_supported || !ARB_multitexture_supported ||
            !NV_vertex_program_supported || !NV_register_combiners_supported)
        return false;

    //Check we have at least 3 texture units
    GLint maxTextureUnitsARB;
    glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnitsARB);

    if(maxTextureUnitsARB<3)
    {
        errorLog.OutputError("I require at least 3 texture units");
        return false;
    }

    //Set light colors
    lightColors[0].Set(1.0f, 1.0f, 1.0f, 1.0f);
    lightColors[1].Set((float)47/255, (float)206/255, (float)240/255, 1.0f);
    lightColors[2].Set((float)254/255, (float)48/255, (float)18/255, 1.0f);
    lightColors[3].Set((float)83/255, (float)243/255, (float)29/255, 1.0f);



    //Load textures
    //Decal image
    decalImage.Load("decal.tga");
    glGenTextures(1, &decalTexture);
    glBindTexture(GL_TEXTURE_2D, decalTexture);
    glTexImage2D(	GL_TEXTURE_2D, 0, GL_RGBA8, decalImage.width, decalImage.height,
                    0, decalImage.format, GL_UNSIGNED_BYTE, decalImage.data);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);


    //Create light textures
    if(!InitLightTextures(	atten1DTexture, atten2DTexture, atten3DTexture,
                            gaussian1DTexture, gaussian2DTexture))
        return false;


    camera.Init(VECTOR3D(0.0f, 0.0f, 3.5f));

    //reset timer for start
    timer.Reset();

    return true;
}
示例#6
0
bool LoadNV_vertex_program(char * filename, GLuint programID)
{
	//load from file
	std::ifstream vpFile(filename, std::ios::in | std::ios::binary);
	if(vpFile.fail())
	{
		printf("Unable to open vertex program\n");
		return false;
	}

	//calculate the size of the file
	vpFile.seekg(0, std::ios::end);
	int vpSize=vpFile.tellg();
	vpFile.seekg(0, std::ios::beg);
	
	//allocate memory
	unsigned char * vpText=new unsigned char[vpSize];
	if(!vpText)
	{
		printf("Unable to allocate space for vertex program text\n");
		return false;
	}

	//read file
	vpFile.read(reinterpret_cast<char *>(vpText), vpSize);
	vpFile.close();

	//load program
	glLoadProgramNV(GL_VERTEX_PROGRAM_NV, programID, vpSize, vpText);
	
	if(vpText)
		delete [] vpText;
	vpText=NULL;

	//Output if there was an error
	int errorPos;
	glGetIntegerv(GL_PROGRAM_ERROR_POSITION_NV, &errorPos);
	if(errorPos!=-1)
	{
		errorLog.OutputError("Program error at position %d in %s\n", errorPos, filename);
		return false;
	}
	else
		errorLog.OutputSuccess("%s loaded correctly", filename);

	return true;
}
示例#7
0
bool PBUFFER::MakeCurrent()
{
	if(!wglMakeCurrent(hDC, hRC))
	{
		errorLog.OutputError("Unable to change current context");
		return false;
	}

	return true;
}
bool SetUpEXT_texture_edge_clamp()
{
	//Check for support
	char * extensionString=(char *)glGetString(GL_EXTENSIONS);
	char * extensionName="GL_EXT_texture_edge_clamp";

	char * endOfString;									//store pointer to end of string
	unsigned int distanceToSpace;						//distance to next space

	endOfString=extensionString+strlen(extensionString);

	//loop through string
	while(extensionString<endOfString)
	{
		//find distance to next space
		distanceToSpace=strcspn(extensionString, " ");

		//see if we have found extensionName
		if((strlen(extensionName)==distanceToSpace) &&
			(strncmp(extensionName, extensionString, distanceToSpace)==0))
		{
			EXT_texture_edge_clamp_supported=true;
		}

		//if not, move on
		extensionString+=distanceToSpace+1;
	}

	if(!EXT_texture_edge_clamp_supported)
	{
		errorLog.OutputError("EXT_texture_edge_clamp unsupported!");
		return false;
	}

	errorLog.OutputSuccess("EXT_texture_edge_clamp supported!");

	//get function pointers
	//none specified

	return true;
}
示例#9
0
//Load a TGA texture
bool IMAGE::LoadTGA(char * filename)
{
	unsigned char	UncompressedTGAHeader[12]={0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0};
	unsigned char	CompressedTGAHeader[12]={0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0};
	unsigned char	Uncompressed8BitTGAHeader[12]={0, 1, 1, 0, 0, 0, 1, 24, 0, 0, 0, 0};

	unsigned char	TGAcompare[12];						//Used to compare TGA header
	
	FILE * file = fopen(filename, "rb");		//Open the TGA file
	
	if(	file==NULL )							//Does the file exist?
	{
		errorLog.OutputError("%s does not exist", filename);
		return false;
	}
	
	//read the header
	fread(TGAcompare, 1, sizeof(TGAcompare), file);
	fclose(file);

	if(memcmp(UncompressedTGAHeader, TGAcompare, sizeof(UncompressedTGAHeader))==0)
	{
		return LoadUncompressedTrueColorTGA(filename);
	}
	else if(memcmp(CompressedTGAHeader, TGAcompare, sizeof(CompressedTGAHeader))==0)
	{
		return LoadCompressedTrueColorTGA(filename);
	}
	else if(memcmp(Uncompressed8BitTGAHeader, TGAcompare, sizeof(Uncompressed8BitTGAHeader))==0)
	{
		return LoadUncompressed8BitTGA(filename);
	}
	else
	{
		errorLog.OutputError("%s is not a recognised type of TGA", filename);
		return false;
	}
	
	return false;
}
示例#10
0
bool IMAGE::LoadBMP(char * filename)
{
	FILE * file;												//the texture file
	BITMAPFILEHEADER fileHeader;								//bitmap file header
	BITMAPINFOHEADER infoHeader;								//bitmap info header

	//open file for reading
	file=fopen(filename, "rb");
	if(file==NULL)
	{
		errorLog.OutputError("Unable to open %s", filename);
		return false;
	}

	//read the file header
	fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, file);

	//check it's a bitmap
	if(fileHeader.bfType != BITMAP_ID)
	{
		fclose(file);
		errorLog.OutputError("%s is not a legal .BMP", filename);
		return false;
	}

	//read in the information header
	fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, file);

	//close the file
	fclose(file);

	//discover the bpp
	if(infoHeader.biBitCount==24)
		return Load24BitBMP(filename);
	if(infoHeader.biBitCount==8)
		return Load8BitBMP(filename);

	errorLog.OutputError("%s has an unknown bpp", filename);
	return false;
}
示例#11
0
void PBUFFER::Shutdown(void)
{
	if(hRC)													//have a rendering context?
	{
		if(!wglDeleteContext(hRC))							//try to delete RC
		{
			errorLog.OutputError("Release of Pbuffer Rendering Context Failed.");
		}
		
		hRC=NULL;											//set RC to NULL
	}

	if(hDC && !wglReleasePbufferDCARB(hBuffer, hDC))		//Are we able to release DC?
	{
		errorLog.OutputError("Release of Pbuffer Device Context Failed.");
		hDC=NULL;
	}
	
	if(!wglDestroyPbufferARB(hBuffer))
	{
		errorLog.OutputError("Unable to destroy pbuffer");
	}
}
示例#12
0
void IMAGE::FlipVertically()
{
	//dont flip zero or 1 height images
	if(height==0 || height==1)
		return;

	int rowsToSwap=0;
	//see how many rows to swap
	if(height%2==1)
		rowsToSwap=(height-1)/2;
	else
		rowsToSwap=height/2;

	//create space for a temporary row
	GLubyte * tempRow=new GLubyte[width*bpp/8];
	if(!tempRow)
	{
		errorLog.OutputError("Unable to flip image, unable to create space for temporary row");
		return;
	}

	//loop through rows to swap
	for(int i=0; i<rowsToSwap; ++i)
	{
		//copy row i into temp
		memcpy(tempRow, &data[i*width*bpp/8], width*bpp/8);
		//copy row height-i-1 to row i
		memcpy(&data[i*width*bpp/8], &data[(height-i-1)*width*bpp/8], width*bpp/8);
		//copy temp into row height-i-1
		memcpy(&data[(height-i-1)*width*bpp/8], tempRow, width*bpp/8);
	}

	//free tempRow
	if(tempRow)
		delete [] tempRow;
	tempRow=NULL;
}
示例#13
0
//ENTRY POINT FOR APPLICATION
//CALL WINDOW CREATION ROUTINE, DEAL WITH MESSAGES, WATCH FOR INTERACTION
int WINAPI WinMain(	HINSTANCE	hInstance,				//instance
					HINSTANCE	hPrevInstance,			//Previous Instance
					LPSTR		lpCmdLine,				//command line parameters
					int			nCmdShow)				//Window show state
{
	//Initiation
	errorLog.Init("Error Log.txt");

	//init variables etc, then GL
	if(!DemoInit())
	{
		errorLog.OutputError("Demo Initiation failed");
		return 0;
	}
	else
		errorLog.OutputSuccess("Demo Initiation Successful");

	if(!GLInit())
	{
		errorLog.OutputError("OpenGL Initiation failed");
		return 0;
	}
	else
		errorLog.OutputSuccess("OpenGL Initiation Successful");

	//Main Loop
	for(;;)
	{
		if(!(window.HandleMessages())) break;//handle windows messages, quit if returns false
		UpdateFrame();
		RenderFrame();
	}

	DemoShutdown();
	
	errorLog.OutputSuccess("Exiting...");
	return (window.msg.wParam);								//Exit The Program
}
示例#14
0
bool PBUFFER::Init(	int newWidth, int newHeight,
					int newColorBits, int newDepthBits, int newStencilBits,
					int numExtraIAttribs, int * extraIAttribList, int * flags)
{
	//Check for pbuffer support
	if(	!WGL_ARB_extensions_string_supported ||
		!WGL_ARB_pixel_format_supported ||
		!WGL_ARB_pbuffer_supported)
	{
		errorLog.OutputError("Extension required for pbuffer unsupported");
		return false;
	}

	//set class's member variables
	width=newWidth;
	height=newHeight;
	colorBits=newColorBits;
	depthBits=newDepthBits;
	stencilBits=newStencilBits;

	//Get the current device context
	HDC hCurrentDC=wglGetCurrentDC();
	if(!hCurrentDC)
	{
		errorLog.OutputError("Unable to get current Device Context");
		return false;
	}
	

	//choose pixel format
	GLint pixelFormat;

	const int standardIAttribList[]={	WGL_DRAW_TO_PBUFFER_ARB, 1,
										WGL_COLOR_BITS_ARB, colorBits,
										WGL_ALPHA_BITS_ARB, colorBits==32 ? 8 : 0,
										WGL_DEPTH_BITS_ARB, depthBits,
										WGL_STENCIL_BITS_ARB, stencilBits};
	const float fAttribList[]={	
										0};

	//add the extraIAttribList to the standardIAttribList
	int * iAttribList=new int[sizeof(standardIAttribList)/sizeof(int)+numExtraIAttribs*2+1];
	if(!iAttribList)
	{
		errorLog.OutputError("Unable to allocate space for iAttribList");
		return false;
	}

	memcpy(	iAttribList, standardIAttribList, sizeof(standardIAttribList));
	memcpy( iAttribList+sizeof(standardIAttribList)/sizeof(int),
			extraIAttribList, numExtraIAttribs*2*sizeof(int)+sizeof(int));

	//Choose pixel format
	unsigned int numFormats;
	if(!wglChoosePixelFormatARB(hCurrentDC, iAttribList, fAttribList, 1,
								&pixelFormat, &numFormats))
	{
		errorLog.OutputError("Unable to find a pixel format for the pbuffer");
		return false;
	}

	//Create the pbuffer
	hBuffer=wglCreatePbufferARB(hCurrentDC, pixelFormat, width, height, flags);
	if(!hBuffer)
	{
		errorLog.OutputError("Unable to create pbuffer");
		return false;
	}

	//Get the pbuffer's device context
	hDC=wglGetPbufferDCARB(hBuffer);
	if(!hDC)
	{
		errorLog.OutputError("Unable to get pbuffer's device context");
		return false;
	}

	//Create a rendering context for the pbuffer
	hRC=wglCreateContext(hDC);
	if(!hRC)
	{
		errorLog.OutputError("Unable to create pbuffer's rendering context");
		return false;
	}

	//Set and output the actual pBuffer dimensions
	wglQueryPbufferARB(hBuffer, WGL_PBUFFER_WIDTH_ARB, &width);
	wglQueryPbufferARB(hBuffer, WGL_PBUFFER_HEIGHT_ARB, &height);
	errorLog.OutputSuccess("Pbuffer Created: (%d x %d)", width, height);
	
	return TRUE;										//success!
}
示例#15
0
//Set up variables
bool DemoInit()
{
	if(!window.Init("Project Template", 640, 480, 32, 24, 8, WINDOWED_SCREEN))
		return 0;											//quit if not created

	SetUpARB_multitexture();
	SetUpARB_texture_cube_map();
	SetUpEXT_texture_edge_clamp();
	SetUpNV_register_combiners();
	SetUpNV_register_combiners2();
	SetUpNV_vertex_program();

	//Check for necessary extensions
	if(	!ARB_multitexture_supported || !ARB_texture_cube_map_supported ||
		!EXT_texture_edge_clamp_supported || !NV_register_combiners_supported ||
		!NV_vertex_program_supported)
		return false;

	//Check for single-pass chromatic aberration states
	GLint maxTextureUnits;
	glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits);
	if( NV_register_combiners2_supported && maxTextureUnits>=4)
	{
		errorLog.OutputSuccess("Single Pass Chromatic Aberration Supported!");
		pathOneSupported=true;
		renderPath=CHROMATIC_SINGLE;
	}

	camera.Init(VECTOR3D(0.0f, 0.0f, 4.0f), 2.5f, 10.0f);

	if(	!cubeMapPosX.Load("cube_face_posx.tga") ||
		!cubeMapNegX.Load("cube_face_negx.tga") ||
		!cubeMapPosY.Load("cube_face_posy.tga") ||
		!cubeMapNegY.Load("cube_face_negy.tga") ||
		!cubeMapPosZ.Load("cube_face_posz.tga") ||
		!cubeMapNegZ.Load("cube_face_negz.tga"))
		return false;

	//Build a texture from the data
	glGenTextures(1, &cubeMapTexture);								//Generate Texture ID
	glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, cubeMapTexture);					//Bind texture
	
	glTexImage2D(	GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
					0, GL_RGBA8, cubeMapPosX.width, cubeMapPosX.height, 0,
					cubeMapPosX.format, GL_UNSIGNED_BYTE, cubeMapPosX.data);
	
	glTexImage2D(	GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
					0, GL_RGBA8, cubeMapNegX.width, cubeMapNegX.height, 0,
					cubeMapNegX.format, GL_UNSIGNED_BYTE, cubeMapNegX.data);

	glTexImage2D(	GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
					0, GL_RGBA8, cubeMapPosY.width, cubeMapPosY.height, 0,
					cubeMapPosY.format, GL_UNSIGNED_BYTE, cubeMapPosY.data);
	
	glTexImage2D(	GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
					0, GL_RGBA8, cubeMapNegY.width, cubeMapNegY.height, 0,
					cubeMapNegY.format, GL_UNSIGNED_BYTE, cubeMapNegY.data);

	glTexImage2D(	GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
					0, GL_RGBA8, cubeMapPosZ.width, cubeMapPosZ.height, 0,
					cubeMapPosZ.format, GL_UNSIGNED_BYTE, cubeMapPosZ.data);
	
	glTexImage2D(	GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
					0, GL_RGBA8, cubeMapNegZ.width, cubeMapNegZ.height, 0,
					cubeMapNegZ.format, GL_UNSIGNED_BYTE, cubeMapNegZ.data);

	glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

	
	//reset timer for start
	timer.Reset();
	
	return true;
}
示例#16
0
//load in an 8 bit greyscale TGA as an alpha channel
bool IMAGE::LoadAlphaTGA(char * filename)
{
	unsigned char	TGAHeader[12]={0, 1, 1, 0, 0, 0, 1, 24, 0, 0, 0, 0};
	unsigned char	TGAcompare[12];						//Used to compare TGA header
	unsigned char	header[6];							//First 6 useful bytes of the header
		
	errorLog.OutputSuccess("Loading %s in LoadAlphaTGA()", filename);

	if(!(format==GL_RGB || format==GL_RGBA))
	{
		errorLog.OutputError("Can only load an alpha channel to RGB / RGBA format images. %s caused error", filename);
		return false;
	}

	FILE * file = fopen(filename, "rb");				//Open the TGA file
	
	if(file == NULL)								//Does the file exist?
	{
		errorLog.OutputError("%s does not exist.", filename);
		return false;
	}

	if(	fread(TGAcompare, 1, sizeof(TGAcompare), file)!=sizeof(TGAcompare)||	//Are there 12 bytes to read?
		memcmp(TGAHeader, TGAcompare, sizeof(TGAHeader))!=0	||					//Is the header correct?
		fread(header, 1, sizeof(header), file)!=sizeof(header))		//Read next 6 bytes
	{
		fclose(file);								//If anything else failed, close the file
		errorLog.OutputError("Could not load %s correctly, general failure.", filename);
		return false;
	}
	
	//save data into class member variables
	unsigned int alphaWidth=	header[1]*256+header[0];						//determine the image width
	unsigned int alphaHeight=	header[3]*256+header[2];						//determine image height
	int alphaBpp=				header[4];

	if(	alphaWidth<=0	||											//if width <=0
		alphaHeight<=0	||											//or height<=0
		alphaBpp!=8)												//bpp not 8
	{
		fclose(file);											//close the file
		errorLog.OutputError("%s's height or width is less than zero, or the TGA is not 8 bpp.", filename);
		return false;
	}

	//check it is the same size as the image
	if(alphaWidth!=width || alphaHeight!=height)
	{
		errorLog.OutputError("%s is not the same size as the color texture", filename);
		return false;
	}

	//make space for palette
	unsigned char * palette=new unsigned char[256*3];
	if(!palette)
	{
		errorLog.OutputError("Unable to allocate memory for palette");
		return false;
	}
	
	//load the palette
	fread(palette, 256*3, 1, file);
	
	//we dont use the palette
	delete [] palette;
	palette=NULL;

	//allocate space for alpha values
	unsigned char * values=new unsigned char[width*height];
	if(!values)
	{
		errorLog.OutputError("Unable to allocate memory for alpha values");
		return false;
	}
	
	//load indices
	fread(values, 1, alphaWidth*alphaHeight, file);

	//close the file
	fclose(file);

	//now put in the alpha data
	if(format==GL_RGBA)
	{
		for(unsigned int i=0; i<width*height; i++)
		{
			data[i*4+3]=values[i];
		}
	}
	else if(format==GL_RGB)
	{
		unsigned char * tempData=new unsigned char[width*height*4];
		if(!tempData)
		{
			errorLog.OutputError("Unable to allocate memory for Temporary Data");
			return false;
		}

		for(unsigned int i=0; i<width*height; i++)
		{
			tempData[i*4+0]=data[i*3+0];
			tempData[i*4+1]=data[i*3+1];
			tempData[i*4+2]=data[i*3+2];
			tempData[i*4+3]=values[i];
		}

		//update member variables
		bpp=32;
		format=GL_RGBA;

		if(data)
			delete [] data;
		data=tempData;
	}

	errorLog.OutputSuccess("Loaded %s correctly.", filename);
	return true;
}
示例#17
0
//Load24BitBMP - load a 24 bit bitmap file
bool IMAGE::Load24BitBMP(char * filename)
{
	errorLog.OutputSuccess("Loading %s in Load24bitBMP()", filename);
	
	//set bpp and format
	bpp=24;
	format=GL_RGB;

	FILE * file;												//the texture file
	BITMAPFILEHEADER fileHeader;								//bitmap file header
	BITMAPINFOHEADER infoHeader;								//bitmap info header

	//open file for reading
	file=fopen(filename, "rb");
	if(file==NULL)
	{
		errorLog.OutputError("Unable to open %s", filename);
		return false;
	}

	//read the file header
	fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, file);

	//check it's a bitmap
	if(fileHeader.bfType != BITMAP_ID)
	{
		fclose(file);
		errorLog.OutputError("%s is not a legal .BMP", filename);
		return false;
	}

	//read in the information header
	fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, file);

	//set size
	width=infoHeader.biWidth;
	height=infoHeader.biHeight;

	//calculate the stride in bytes: width*bpp/8 plus padding bytes at the end of each row
	unsigned int stride=width*bpp/8;
	if(width%4==1)
		stride+=1;
	if(width%4==2)
		stride+=2;
	if(width%4==3)
		stride+=3;

	//point file to the beginning of the data
	fseek(file, fileHeader.bfOffBits, SEEK_SET);

	//allocate space for the image data
	data=new unsigned char[stride*height];
	if(!data)
	{
		fclose(file);
		errorLog.OutputError("Unable to allocate memory for %s", filename);
		return false;
	}

	//read in the data
	fread(data, 1, stride*height, file);

	//close the file
	fclose(file);

	//data is in BGR format
	//swap b and r
	for(unsigned int row=0; row<height; row++)
	{
		for(unsigned int i=0; i<width*3; i+=bpp/8)
		{	
			//repeated XOR to swap bytes 0 and 2
			data[(row*stride)+i] ^= data[(row*stride)+i+2] ^=
				data[(row*stride)+i] ^= data[(row*stride)+i+2];
		}
	}

	errorLog.OutputSuccess("Loaded %s correctly.", filename);
	return true;
}
示例#18
0
//load an uncompressed TGA texture (24 or 32 bpp)
bool IMAGE::LoadUncompressedTrueColorTGA(char * filename)
{
	unsigned char	TGAheader[12]={0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0};	//Uncompressed TGA header
	unsigned char	TGAcompare[12];						//Used to compare TGA header
	unsigned char	header[6];							//First 6 useful bytes of the header
	unsigned int	bytesPerPixel;						//bytes per pixel
	unsigned int	imageSize;							//Stores Image size when in RAM
		
	errorLog.OutputSuccess("Loading %s in LoadUncompressedTGA()", filename);

	FILE * file = fopen(filename, "rb");				//Open the TGA file
	
	if(file == NULL)								//Does the file exist?
	{
		errorLog.OutputError("%s does not exist.", filename);
		return false;
	}

	if(	fread(TGAcompare, 1, sizeof(TGAcompare), file)!=sizeof(TGAcompare)||	//Are there 12 bytes to read?
		memcmp(TGAheader, TGAcompare, sizeof(TGAheader))!=0	||					//Is the header correct?
		fread(header, 1, sizeof(header), file)!=sizeof(header))		//Read next 6 bytes
	{
		fclose(file);								//If anything else failed, close the file
		errorLog.OutputError("Could not load %s correctly, general failure.", filename);
		return false;
	}
	
	//save data into class member variables
	width=	header[1]*256+header[0];						//determine the image width
	height=	header[3]*256+header[2];						//determine image height
	bpp=	header[4];

	if(	width<=0	||											//if width <=0
		height<=0	||											//or height<=0
		bpp!=24 && bpp!=32)										//bpp not 24 or 32
	{
		fclose(file);											//close the file
		errorLog.OutputError("%s's height or width is less than zero, or the TGA is not 24 or 32 bpp.", filename);
		return false;
	}

	//set format
	if(bpp == 24)
		format=GL_RGB;
	else
		format=GL_RGBA;

	bytesPerPixel=bpp/8;										//calc bytes per pixel
	imageSize=width*height*bytesPerPixel;						//calc memory required

	data=new unsigned char[imageSize];							//reserve the memory for the data

	if(	data==NULL)											//Does the storage memory exist?
	{
		errorLog.OutputError("Unable to allocate memory for %s image", filename);
		fclose(file);
		return false;
	}
	
	//read in the image data
	if(fread(data, 1, imageSize, file)!=imageSize)				//Does the image size match the required?
	{															//If not
		if(data)												//If data loaded
			delete [] data;										//free memory
		errorLog.OutputError("Could not read %s image data", filename);
		fclose(file);											//close file
		return false;
	}

	fclose(file);

	//data is in BGR format
	//swap b and r
	for(int i=0; i<(int)imageSize; i+=bytesPerPixel)
	{	
		//repeated XOR to swap bytes 0 and 2
		data[i] ^= data[i+2] ^= data[i] ^= data[i+2];
	}
	
	errorLog.OutputSuccess("Loaded %s correctly.", filename);
	return true;
}
示例#19
0
//load a compressed TGA texture (24 or 32 bpp)
bool IMAGE::LoadCompressedTrueColorTGA(char * filename)
{
	unsigned char	TGAheader[12]={0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0};	//Compressed TGA header
	unsigned char	TGAcompare[12];						//Used to compare TGA header
	unsigned char	header[6];							//First 6 useful bytes of the header
	unsigned int	bytesPerPixel;						//bytes per pixel
	unsigned int	imageSize;							//Stores Image size when in RAM
		
	errorLog.OutputSuccess("Loading %s in LoadCompressedTGA()", filename);

	FILE * file = fopen(filename, "rb");				//Open the TGA file
	
	if(file == NULL)								//Does the file exist?
	{
		errorLog.OutputError("%s does not exist.", filename);
		return false;
	}

	if(	fread(TGAcompare, 1, sizeof(TGAcompare), file)!=sizeof(TGAcompare)||	//Are there 12 bytes to read?
		memcmp(TGAheader, TGAcompare, sizeof(TGAheader))!=0	||					//Is the header correct?
		fread(header, 1, sizeof(header), file)!=sizeof(header))		//Read next 6 bytes
	{
		fclose(file);								//If anything else failed, close the file
		errorLog.OutputError("Could not load %s correctly, general failure.", filename);
		return false;
	}
	
	//save data into class member variables
	width=	header[1]*256+header[0];						//determine the image width
	height=	header[3]*256+header[2];						//determine image height
	bpp=	header[4];

	if(	width<=0	||											//if width <=0
		height<=0	||											//or height<=0
		bpp!=24 && bpp!=32)										//bpp not 24 or 32
	{
		fclose(file);											//close the file
		errorLog.OutputError("%s's height or width is less than zero, or the TGA is not 24 or 32 bpp.", filename);
		return false;
	}

	//set format
	if(bpp == 24)
		format=GL_RGB;
	else
		format=GL_RGBA;

	bytesPerPixel=bpp/8;										//calc bytes per pixel
	imageSize=width*height*bytesPerPixel;						//calc memory required

	data=new unsigned char[imageSize];							//reserve the memory for the data
	if(!data)													//Does the storage memory exist?
	{
		errorLog.OutputError("Unable to allocate memory for %s image", filename);
		fclose(file);
		return false;
	}
	
	//read in the image data
	int pixelCount	= height*width;
	int currentPixel= 0;
	int currentByte	= 0;
	unsigned char * colorBuffer=new unsigned char[bytesPerPixel];

	do
	{
		unsigned char chunkHeader=0;

		if(fread(&chunkHeader, sizeof(unsigned char), 1, file) == 0)
		{
			errorLog.OutputError("Could not read RLE chunk header");
			if(file)
				fclose(file);
			if(data)
				delete [] data;
			return false;
		}

		if(chunkHeader<128)	//Read raw color values
		{
			chunkHeader++;

			for(short counter=0; counter<chunkHeader; counter++)
			{
				if(fread(colorBuffer, 1, bytesPerPixel, file) != bytesPerPixel)
				{
					errorLog.OutputError("Unable to read %s image data", filename);
					
					if(file)
						fclose(file);

					if(colorBuffer)
						delete [] colorBuffer;

					if(data)
						delete [] data;

					return false;
				}

				//transfer pixel color to data (swapping r and b values)
				data[currentByte] = colorBuffer[2];
				data[currentByte+1] = colorBuffer[1];
				data[currentByte+2] = colorBuffer[0];

				if(bytesPerPixel==4)
					data[currentByte+3]=colorBuffer[3];

				currentByte+=bytesPerPixel;
				currentPixel++;

				if(currentPixel > pixelCount)
				{
					errorLog.OutputError("Too many pixels read");
					if(file)
						fclose(file);
					if(colorBuffer)
						delete [] colorBuffer;
					if(data)
						delete [] data;
					return false;
				}
			}
		}
		else	//chunkHeader>=128
		{
			chunkHeader-=127;

			if(fread(colorBuffer, 1, bytesPerPixel, file) != bytesPerPixel)
			{
				errorLog.OutputError("Unable to read %s image data", filename);
					
				if(file)
					fclose(file);
				if(colorBuffer)
					delete [] colorBuffer;
				if(data)
					delete [] data;
				return false;
			}

			for(short counter=0; counter<chunkHeader; counter++)
			{
				//transfer pixel color to data (swapping r and b values)
				data[currentByte] = colorBuffer[2];
				data[currentByte+1] = colorBuffer[1];
				data[currentByte+2] = colorBuffer[0];

				if(bytesPerPixel==4)
					data[currentByte+3]=colorBuffer[3];

				currentByte+=bytesPerPixel;
				currentPixel++;

				if(currentPixel > pixelCount)
				{
					errorLog.OutputError("Too many pixels read");
					if(file)
						fclose(file);
					if(colorBuffer)
						delete [] colorBuffer;
					if(data)
						delete [] data;
					return false;
				}
			}
		}
	}while(currentPixel<pixelCount);

	fclose(file);

	errorLog.OutputSuccess("Loaded %s correctly.", filename);
	return true;
}
示例#20
0
//load an 8 bit uncompressed paletted TGA
bool IMAGE::LoadUncompressed8BitTGA(char * filename)
{
	unsigned char		TGAHeader[12]={0, 1, 1, 0, 0, 0, 1, 24, 0, 0, 0, 0};
	unsigned char		TGAcompare[12];						//Used to compare TGA header
	unsigned char		header[6];							//First 6 useful bytes of the header
		
	errorLog.OutputSuccess("Loading %s in LoadUncompressed8BitTGA()", filename);

	FILE * file = fopen(filename, "rb");				//Open the TGA file
	
	if(file == NULL)								//Does the file exist?
	{
		errorLog.OutputError("%s does not exist.", filename);
		return false;
	}

	if(	fread(TGAcompare, 1, sizeof(TGAcompare), file)!=sizeof(TGAcompare)||	//Are there 12 bytes to read?
		memcmp(TGAHeader, TGAcompare, sizeof(TGAHeader))!=0	||					//Is the header correct?
		fread(header, 1, sizeof(header), file)!=sizeof(header))		//Read next 6 bytes
	{
		fclose(file);								//If anything else failed, close the file
		errorLog.OutputError("Could not load %s correctly, general failure.", filename);
		return false;
	}
	
	//save data into class member variables
	width=	header[1]*256+header[0];						//determine the image width
	height=	header[3]*256+header[2];						//determine image height
	bpp=	header[4];

	if(	width<=0	||											//if width <=0
		height<=0	||											//or height<=0
		bpp!=8)													//bpp not 8
	{
		fclose(file);											//close the file
		errorLog.OutputError("%s's height or width is less than zero, or the TGA is not 8 bpp.", filename);
		return false;
	}

	//set format
	format=GL_RGB;

	//make space for palette
	unsigned char * palette=new unsigned char[256*3];
	if(!palette)
	{
		errorLog.OutputError("Unable to allocate memory for palette");
		return false;
	}
	
	//load the palette
	fread(palette, 256*3, 1, file);
	
	//allocate space for color indices
	unsigned char * indices=new unsigned char[width*height];
	if(!indices)
	{
		errorLog.OutputError("Unable to allocate memory for indices");
		return false;
	}
	
	//load indices
	fread(indices, 1, width*height, file);

	//close the file
	fclose(file);

	//allocate space for the image data
	data=new unsigned char[width*height*3];
	if(!data)
	{
		fclose(file);
		errorLog.OutputError("Unable to allocate memory for %s", filename);
		return false;
	}

	//calculate the color values
	for(unsigned int currentRow=0; currentRow<height; currentRow++)
	{
		for(unsigned int i=0; i<width; i++)
		{
			data[(currentRow*width+i)*3+0]=palette[indices[currentRow*width+i]*3+2];
			data[(currentRow*width+i)*3+1]=palette[indices[currentRow*width+i]*3+1];
			data[(currentRow*width+i)*3+2]=palette[indices[currentRow*width+i]*3+0];//BGR
		}
	}
	
	errorLog.OutputSuccess("Loaded %s correctly.", filename);
	return true;
}
示例#21
0
///////////////////BSP::LoadBSPData/////////
////////////////////////////////////////////
bool BSP::LoadBSPData(FILE * file)
{
	//Load leaves
	//Calculate number of leaves
	numLeaves=header.directoryEntries[bspLeaves].length/sizeof(BSP_LOAD_LEAF);

	//Create space for this many BSP_LOAD_LEAFS
	BSP_LOAD_LEAF * loadLeaves=new BSP_LOAD_LEAF[numLeaves];
	if(!loadLeaves)
	{
		errorLog.OutputError("Unable to allocate space for %d BSP_LOAD_LEAFs", numLeaves);
		return false;
	}

	//Create space for this many BSP_LEAFs
	leaves=new BSP_LEAF[numLeaves];
	if(!leaves)
	{
		errorLog.OutputError("Unable to allocate space for %d BSP_LEAFs", numLeaves);
		return false;
	}

	//Load leaves
	fseek(file, header.directoryEntries[bspLeaves].offset, SEEK_SET);
	fread(loadLeaves, 1, header.directoryEntries[bspLeaves].length, file);

	//Convert the load leaves to leaves
	for(int i=0; i<numLeaves; ++i)
	{
		leaves[i].cluster=loadLeaves[i].cluster;
		leaves[i].firstLeafFace=loadLeaves[i].firstLeafFace;
		leaves[i].numFaces=loadLeaves[i].numFaces;

		//Create the bounding box
		leaves[i].boundingBoxVertices[0].Set((float)loadLeaves[i].mins[0], (float)loadLeaves[i].mins[2],-(float)loadLeaves[i].mins[1]);
		leaves[i].boundingBoxVertices[1].Set((float)loadLeaves[i].mins[0], (float)loadLeaves[i].mins[2],-(float)loadLeaves[i].maxs[1]);
		leaves[i].boundingBoxVertices[2].Set((float)loadLeaves[i].mins[0], (float)loadLeaves[i].maxs[2],-(float)loadLeaves[i].mins[1]);
		leaves[i].boundingBoxVertices[3].Set((float)loadLeaves[i].mins[0], (float)loadLeaves[i].maxs[2],-(float)loadLeaves[i].maxs[1]);
		leaves[i].boundingBoxVertices[4].Set((float)loadLeaves[i].maxs[0], (float)loadLeaves[i].mins[2],-(float)loadLeaves[i].mins[1]);
		leaves[i].boundingBoxVertices[5].Set((float)loadLeaves[i].maxs[0], (float)loadLeaves[i].mins[2],-(float)loadLeaves[i].maxs[1]);
		leaves[i].boundingBoxVertices[6].Set((float)loadLeaves[i].maxs[0], (float)loadLeaves[i].maxs[2],-(float)loadLeaves[i].mins[1]);
		leaves[i].boundingBoxVertices[7].Set((float)loadLeaves[i].maxs[0], (float)loadLeaves[i].maxs[2],-(float)loadLeaves[i].maxs[1]);

		for(int j=0; j<8; ++j)
			leaves[i].boundingBoxVertices[j]/=64;
	}

	
	
	//Load leaf faces array
	int numLeafFaces=header.directoryEntries[bspLeafFaces].length/sizeof(int);

	//Create space for this many leaf faces
	leafFaces=new int[numLeafFaces];
	if(!leafFaces)
	{
		errorLog.OutputError("Unable to allocate space for %d leaf faces", numLeafFaces);
		return false;
	}

	//Load leaf faces
	fseek(file, header.directoryEntries[bspLeafFaces].offset, SEEK_SET);
	fread(leafFaces, 1, header.directoryEntries[bspLeafFaces].length, file);


	
	//Load Planes
	numPlanes=header.directoryEntries[bspPlanes].length/sizeof(PLANE);

	//Create space for this many planes
	planes=new PLANE[numPlanes];
	if(!planes)
	{
		errorLog.OutputError("Unable to allocate space for %d planes", numPlanes);
		return false;
	}

	fseek(file, header.directoryEntries[bspPlanes].offset, SEEK_SET);
	fread(planes, 1, header.directoryEntries[bspPlanes].length, file);

	//reverse the intercept on the planes and convert planes to OGL coordinates
	for(int i=0; i<numPlanes; ++i)
	{
		//swap y and z and negate z
		float temp=planes[i].normal.y;
		planes[i].normal.y=planes[i].normal.z;
		planes[i].normal.z=-temp;

		planes[i].intercept=-planes[i].intercept;
		planes[i].intercept/=64;	//scale down
	}




	//Load nodes
	numNodes=header.directoryEntries[bspNodes].length/sizeof(BSP_NODE);

	//Create space for this many nodes
	nodes=new BSP_NODE[numNodes];
	if(!nodes)
	{
		errorLog.OutputError("Unable to allocate space for %d nodes", numNodes);
		return false;
	}

	fseek(file, header.directoryEntries[bspNodes].offset, SEEK_SET);
	fread(nodes, 1, header.directoryEntries[bspNodes].length, file);





	//Load visibility data
	//load numClusters and bytesPerCluster
	fseek(file, header.directoryEntries[bspVisData].offset, SEEK_SET);
	fread(&visibilityData, 2, sizeof(int), file);

	//Calculate the size of the bitset
	int bitsetSize=visibilityData.numClusters*visibilityData.bytesPerCluster;

	//Create space for bitset
	visibilityData.bitset=new GLubyte[bitsetSize];
	if(!visibilityData.bitset)
	{
		errorLog.OutputError(	"Unable to allocate memory for visibility bitset of size %d bytes",
								bitsetSize);
		return false;
	}
	//read bitset
	fread(visibilityData.bitset, 1, bitsetSize, file);

	if(loadLeaves)
		delete [] loadLeaves;
	loadLeaves=NULL;


	return true;
}
示例#22
0
//LoadPCX - load a .pcx texture - 256 color, paletted
bool IMAGE::LoadPCX(char * filename)
{
	errorLog.OutputSuccess("Loading %s in LoadPCX()", filename);

	//set bpp and format
	bpp=24;
	format=GL_RGB;

	FILE * file;

	file=fopen(filename, "rb");
	if(!file)
	{
		errorLog.OutputError("Unable to open %s", filename);
		return false;
	}

	//retrieve header, first 4 bytes, first 2 should be 0x0A0C
	unsigned short header[2];
	fread(header, 4, 1, file);

	if(header[0]!=0x050A)
	{
		errorLog.OutputError("%s is not a legal .PCX file", filename);
		fclose(file);
		return false;
	}

	//retrieve minimum x value
	int xMin=fgetc(file);		//loword
	xMin |= fgetc(file) << 8;	//hiword

	//retrieve minimum y value
	int yMin=fgetc(file);		//loword
	yMin |= fgetc(file) << 8;	//hiword

	//retrieve maximum x value
	int xMax=fgetc(file);		//loword
	xMax |= fgetc(file) << 8;	//hiword

	//retrieve maximum y value
	int yMax=fgetc(file);		//loword
	yMax |= fgetc(file) << 8;	//hiword

	//calculate width and height
	width = xMax-xMin+1;
	height= yMax-yMin+1;

	//allocate memory for pixel data (paletted)
	unsigned char * pixelData=new unsigned char[width*height];
	if(!pixelData)
	{
		errorLog.OutputError("Unable to allocate %d bytes for the image data of %s",
								width*height, filename);
		fclose(file);
		return false;
	}

	//set file pointer to beginning of image data
	fseek(file, 128, SEEK_SET);

	//decode and store the pixel data
	unsigned int index=0;

	while(index<(width*height))
	{
		int c = getc(file);

		if(c>0xBF)
		{
			int numRepeat = 0x3F & c;
			c=getc(file);

			for(int i=0; i<numRepeat; i++)
				pixelData[index++] = c;
		}
		else
			pixelData[index++] = c;

		fflush(stdout);
	}

	//allocate memory for the image palette
	unsigned char * paletteData = new unsigned char[768];

	//the palette is the last 769 bytes of the file
	fseek(file, -769, SEEK_END);

	//retrieve first character, should be equal to 12
	int c=getc(file);
	if(c!=12)
	{
		errorLog.OutputError("%s is not a legal .PCX file - the palette data has an illegal header, %d",
								filename, c);
		fclose(file);
		return false;
	}

	//read and store the palette
	fread(paletteData, 1, 768, file);
	
	//close the file
	fclose(file);

	//allocate memory for the "unpaletted" data
	data = new unsigned char[width*height*3];
	if(!data)
	{
		errorLog.OutputError("Unable to allocate memory for the expanded data of %s", filename);
		return false;
	}

	//calculate the "unpaletted" data - "flipping" the texture top-bottom
	for(unsigned int j=0; j<height; j++)
	{
		for(unsigned int i=0; i<width; i++)
		{
			data[3*(j*width+i)]		= (unsigned char) paletteData[3*pixelData[(height-1-j)*width+i]];
			data[3*(j*width+i)+1]	= (unsigned char) paletteData[3*pixelData[(height-1-j)*width+i]+1];
			data[3*(j*width+i)+2]	= (unsigned char) paletteData[3*pixelData[(height-1-j)*width+i]+2];
		}
	}

	errorLog.OutputSuccess("Loaded %s correctly.", filename);
	return true;
}
示例#23
0
///////////////////BSP::LoadFaces///////////
////////////////////////////////////////////
bool BSP::LoadFaces(FILE * file, int curveTesselation)
{
	//calculate number of load faces
	numTotalFaces=header.directoryEntries[bspFaces].length/sizeof(BSP_LOAD_FACE);

	//Create space for this many BSP_LOAD_FACES
	BSP_LOAD_FACE * loadFaces=new BSP_LOAD_FACE[numTotalFaces];
	if(!loadFaces)
	{
		errorLog.OutputError("Unable to allocate memory for %d BSP_LOAD_FACEs", numTotalFaces);
		return false;
	}

	//go to faces in file
	fseek(file, header.directoryEntries[bspFaces].offset, SEEK_SET);

	//read in the faces
	fread(loadFaces, header.directoryEntries[bspFaces].length, 1, file);


	//Create space for face directory
	faceDirectory=new BSP_FACE_DIRECTORY_ENTRY[numTotalFaces];
	if(!faceDirectory)
	{
		errorLog.OutputError(	"Unable to allocate space for face directory with %d entries",
								numTotalFaces);
		return false;
	}
	
	//Clear the face directory
	memset(faceDirectory, 0, numTotalFaces*sizeof(BSP_FACE_DIRECTORY_ENTRY));

	//Init the "faces drawn" bitset
	facesToDraw.Init(numTotalFaces);


	//Calculate how many of each face type there is
	for(int i=0; i<numTotalFaces; ++i)
	{
		if(loadFaces[i].type==bspPolygonFace)
			++numPolygonFaces;
		if(loadFaces[i].type==bspPatch)
			++numPatches;
		if(loadFaces[i].type==bspMeshFace)
			++numMeshFaces;
	}



	//Create space for BSP_POLYGON_FACEs
	polygonFaces=new BSP_POLYGON_FACE[numPolygonFaces];
	if(!polygonFaces)
	{
		errorLog.OutputError("Unable To Allocate memory for BSP_POLYGON_FACEs");
		return false;
	}

	int currentFace=0;
	//convert loadFaces to polygonFaces
	for(int i=0; i<numTotalFaces; ++i)
	{
		if(loadFaces[i].type!=bspPolygonFace)		//skip this loadFace if it is not a polygon face
			continue;

		polygonFaces[currentFace].firstVertexIndex=loadFaces[i].firstVertexIndex;
		polygonFaces[currentFace].numVertices=loadFaces[i].numVertices;
		polygonFaces[currentFace].textureIndex=loadFaces[i].texture;
		polygonFaces[currentFace].lightmapIndex=loadFaces[i].lightmapIndex;

		//fill in this entry on the face directory
		faceDirectory[i].faceType=bspPolygonFace;
		faceDirectory[i].typeFaceNumber=currentFace;

		++currentFace;
	}



	//Create space for BSP_MESH_FACEs
	meshFaces=new BSP_MESH_FACE[numMeshFaces];
	if(!meshFaces)
	{
		errorLog.OutputError("Unable To Allocate memory for BSP_MESH_FACEs");
		return false;
	}

	int currentMeshFace=0;
	//convert loadFaces to faces
	for(int i=0; i<numTotalFaces; ++i)
	{
		if(loadFaces[i].type!=bspMeshFace)		//skip this loadFace if it is not a mesh face
			continue;

		meshFaces[currentMeshFace].firstVertexIndex=loadFaces[i].firstVertexIndex;
		meshFaces[currentMeshFace].numVertices=loadFaces[i].numVertices;
		meshFaces[currentMeshFace].textureIndex=loadFaces[i].texture;
		meshFaces[currentMeshFace].lightmapIndex=loadFaces[i].lightmapIndex;
		meshFaces[currentMeshFace].firstMeshIndex=loadFaces[i].firstMeshIndex;
		meshFaces[currentMeshFace].numMeshIndices=loadFaces[i].numMeshIndices;

		//fill in this entry on the face directory
		faceDirectory[i].faceType=bspMeshFace;
		faceDirectory[i].typeFaceNumber=currentMeshFace;

		++currentMeshFace;
	}
	



	//Create space for BSP_PATCHes
	patches=new BSP_PATCH[numPatches];
	if(!patches)
	{
		errorLog.OutputError("Unable To Allocate memory for BSP_PATCHes");
		return false;
	}

	int currentPatch=0;
	//convert loadFaces to patches
	for(int i=0; i<numTotalFaces; ++i)
	{
		if(loadFaces[i].type!=bspPatch)		//skip this loadFace if it is not a patch
			continue;

		patches[currentPatch].textureIndex=loadFaces[i].texture;
		patches[currentPatch].lightmapIndex=loadFaces[i].lightmapIndex;
		patches[currentPatch].width=loadFaces[i].patchSize[0];
		patches[currentPatch].height=loadFaces[i].patchSize[1];
		
		//fill in this entry on the face directory
		faceDirectory[i].faceType=bspPatch;
		faceDirectory[i].typeFaceNumber=currentPatch;

		//Create space to hold quadratic patches
		int numPatchesWide=(patches[currentPatch].width-1)/2;
		int numPatchesHigh=(patches[currentPatch].height-1)/2;

		patches[currentPatch].numQuadraticPatches=	numPatchesWide*numPatchesHigh;
		patches[currentPatch].quadraticPatches=new BSP_BIQUADRATIC_PATCH
													[patches[currentPatch].numQuadraticPatches];
		if(!patches[currentPatch].quadraticPatches)
		{
			errorLog.OutputError(	"Unable to allocate memory for %d quadratic patches", 
									patches[currentPatch].numQuadraticPatches);
			return false;
		}

		//fill in the quadratic patches
		for(int y=0; y<numPatchesHigh; ++y)
		{
			for(int x=0; x<numPatchesWide; ++x)
			{
				for(int row=0; row<3; ++row)
				{
					for(int point=0; point<3; ++point)
					{
						patches[currentPatch].quadraticPatches[y*numPatchesWide+x].
							controlPoints[row*3+point]=vertices[loadFaces[i].firstVertexIndex+
								(y*2*patches[currentPatch].width+x*2)+
									row*patches[currentPatch].width+point];
					}
				}

				//tesselate the patch
				patches[currentPatch].quadraticPatches[y*numPatchesWide+x].Tesselate(curveTesselation);
			}
		}


		++currentPatch;
	}

	if(loadFaces)
		delete [] loadFaces;
	loadFaces=NULL;

	return true;
}
示例#24
0
////////////////////BSP::Load///////////////
////////////////////////////////////////////
bool BSP::Load(char * filename, int curveTesselation)
{
	FILE * file;

	file=fopen(filename, "rb");
	if(!file)
	{
		errorLog.OutputError("Unable to open %s", filename);
		return false;
	}

	//read in header
	fread(&header, sizeof(BSP_HEADER), 1, file);

	//check header data is correct
	if(	header.string[0]!='I' || header.string[1]!='B' ||
		header.string[2]!='S' || header.string[3]!='P' ||
		header.version  !=0x2E )
	{
		errorLog.OutputError("%s is not a version 0x2E .bsp map file", filename);
		return false;
	}


	//Load in vertices
	if(!LoadVertices(file))
		return false;


	//Load in mesh indices
	//Calculate number of indices
	int numMeshIndices=header.directoryEntries[bspMeshIndices].length/sizeof(int);

	//Create space
	meshIndices=new int[numMeshIndices];
	if(!meshIndices)
	{
		errorLog.OutputError("Unable to allocate memory for %d mesh indices", numMeshIndices);
		return false;
	}

	//read in the mesh indices
	fseek(file, header.directoryEntries[bspMeshIndices].offset, SEEK_SET);
	fread(meshIndices, header.directoryEntries[bspMeshIndices].length, 1, file);

	

	//Load in faces
	if(!LoadFaces(file, curveTesselation))
		return false;

	
	//Load textures
	if(!LoadTextures(file))
		return false;

		
	//Load Lightmaps
	if(!LoadLightmaps(file))
		return false;


	//Load BSP Data
	if(!LoadBSPData(file))
		return false;


	//Load in entity string
	entityString=new char[header.directoryEntries[bspEntities].length];
	if(!entityString)
	{
		errorLog.OutputError(	"Unable to allocate memory for %d length entity string",
								header.directoryEntries[bspEntities].length);
		return false;
	}

	//Go to entity string in file
	fseek(file, header.directoryEntries[bspEntities].offset, SEEK_SET);
	fread(entityString, 1, header.directoryEntries[bspEntities].length, file);

	//Output the entity string
	//errorLog.OutputSuccess("Entity String: %s", entityString);


	fclose(file);

	errorLog.OutputSuccess("%s Loaded successfully", filename);

	return true;
}
示例#25
0
//Load8BitBMP - load an 8 bit paletted bitmap file
bool IMAGE::Load8BitBMP(char * filename)
{
	errorLog.OutputSuccess("Loading %s in Load8bitBMP()", filename);
	
	//set bpp and format
	bpp=24; //after conversion
	format=GL_RGB;

	FILE * file;												//the texture file
	BITMAPFILEHEADER fileHeader;								//bitmap file header
	BITMAPINFOHEADER infoHeader;								//bitmap info header

	//open file for reading
	file=fopen(filename, "rb");
	if(file==NULL)
	{
		errorLog.OutputError("Unable to open %s", filename);
		return false;
	}

	//read the file header
	fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, file);

	//check it's a bitmap
	if(fileHeader.bfType != BITMAP_ID)
	{
		fclose(file);
		errorLog.OutputError("%s is not a legal .BMP", filename);
		return false;
	}

	//read in the information header
	fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, file);

	//set size
	width=infoHeader.biWidth;
	height=infoHeader.biHeight;

	//make space for palette
	unsigned char * palette=new unsigned char[256*4];
	if(!palette)
	{
		errorLog.OutputError("Unable to alllocate memory for palette");
		return false;
	}
	
	//load the palette
	fread(palette, 256*4, 1, file);
	
	//point file to the beginning of the data
	fseek(file, fileHeader.bfOffBits, SEEK_SET);

	//calculate the stride in bytes between one row and the next
	unsigned int stride=width;
	if(width%4 != 0)
		stride+=4-width%4;

	//allocate space for color indices
	unsigned char * indices=new unsigned char[stride*height];
	if(!indices)
	{
		errorLog.OutputError("Unable to allocate memory for indices");
		return false;
	}
	
	//load indices
	fread(indices, 1, stride*height, file);

	//close the file
	fclose(file);

	//allocate space for the image data
	data=new unsigned char[stride*height*bpp/8];
	if(!data)
	{
		fclose(file);
		errorLog.OutputError("Unable to allocate memory for %s", filename);
		return false;
	}

	//calculate the color values - keeping the padding colors
	for(unsigned int currentRow=0; currentRow<height; currentRow++)
	{
		for(unsigned int i=0; i<stride; i++)
		{
			data[(currentRow*stride+i)*3+0]=palette[indices[currentRow*stride+i]*4+2];
			data[(currentRow*stride+i)*3+1]=palette[indices[currentRow*stride+i]*4+1];
			data[(currentRow*stride+i)*3+2]=palette[indices[currentRow*stride+i]*4+0];//BGR
		}
	}
	
	errorLog.OutputSuccess("Loaded %s correctly.", filename);
	return true;
}
示例#26
0
///////////////////BSP::LoadTextures////////
////////////////////////////////////////////
bool BSP::LoadTextures(FILE * file)
{
	//Calculate number of textures
	numTextures=header.directoryEntries[bspTextures].length/sizeof(BSP_LOAD_TEXTURE);

	//Create space for this many BSP_LOAD_TEXTUREs
	BSP_LOAD_TEXTURE * loadTextures=new BSP_LOAD_TEXTURE[numTextures];
	if(!loadTextures)
	{
		errorLog.OutputError("Unable to allocate space for %d BSP_LOAD_TEXTUREs", numTextures);
		return false;
	}

	//Load textures
	fseek(file, header.directoryEntries[bspTextures].offset, SEEK_SET);
	fread(loadTextures, 1, header.directoryEntries[bspTextures].length, file);

	//Create storage space for that many texture identifiers
	decalTextures=new GLuint[numTextures];
	if(!decalTextures)
	{
		errorLog.OutputError("Unable to create storage space for %d texture IDs", numTextures);
		return false;
	}
	
	//Create storage space for that many booleans to tell if texture has loaded
	isTextureLoaded=new bool[numTextures];
	if(!isTextureLoaded)
	{
		errorLog.OutputError("Unable to create storage space for %d booleans", numTextures);
		return false;
	}
	

	//Generate the texture identifiers
	glGenTextures(numTextures, decalTextures);

	//Loop through and create textures
	IMAGE textureImage;				//Image used to load textures

	for(int i=0; i<numTextures; ++i)
	{
		glBindTexture(GL_TEXTURE_2D, decalTextures[i]);
		
		//add file extension to the name
		char tgaExtendedName[68];
		char jpgExtendedName[68];
		strcpy(tgaExtendedName, loadTextures[i].name);
		strcat(tgaExtendedName, ".tga");
		strcpy(jpgExtendedName, loadTextures[i].name);
		strcat(jpgExtendedName, ".jpg");
		
		//Load texture image
		bool isJpgTexture=false;				//have we loaded a jpg?
		if(!textureImage.Load(tgaExtendedName))	//try to load .tga, if not
		{
			if(LoadJPG(&textureImage, jpgExtendedName))	//try to load jpg
			{
				isJpgTexture=true;
				isTextureLoaded[i]=true;
			}
			else
				isTextureLoaded[i]=false;
		}
		else
			isTextureLoaded[i]=true;
		
		//if a jpg texture, need to set UNPACK_ALIGNMENT to 1
		if(isJpgTexture)
			glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

		//Create texture
		gluBuild2DMipmaps(	GL_TEXTURE_2D, GL_RGBA8, textureImage.width, textureImage.height,
							textureImage.format, GL_UNSIGNED_BYTE, textureImage.data);

		glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

		//Set Parameters
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	}

	if(loadTextures)
		delete [] loadTextures;
	loadTextures=NULL;

	return true;
}
示例#27
0
bool TORUS::InitTorus()
{
	numVertices=(torusPrecision+1)*(torusPrecision+1);
	numIndices=2*torusPrecision*torusPrecision*3;

	vertices=new TORUS_VERTEX[numVertices];
	if(!vertices)
	{
		errorLog.OutputError("Unable to allocate memory for torus vertices");
		return false;
	}

	indices=new unsigned int[numIndices];
	if(!indices)
	{
		errorLog.OutputError("Unable to allocate memory for torus indices");
		return false;
	}
	
	//calculate the first ring - inner radius 4, outer radius 1.5
	for(int i=0; i<torusPrecision+1; i++)
	{
		vertices[i].position=VECTOR3D(1.5f, 0.0f, 0.0f).GetRotatedZ(i*360.0f/torusPrecision)+
									VECTOR3D(4.0f, 0.0f, 0.0f);
		
		vertices[i].s=0.0f;
		vertices[i].t=(float)i/torusPrecision;

		vertices[i].sTangent.Set(0.0f, 0.0f, -1.0f);
		vertices[i].tTangent=VECTOR3D(0.0f, -1.0f, 0.0f).GetRotatedZ(i*360.0f/torusPrecision);
		vertices[i].normal=vertices[i].tTangent.
							CrossProduct(vertices[i].sTangent);
	}

	//rotate this to get other rings
	for(int ring=1; ring<torusPrecision+1; ring++)
	{
		for(int i=0; i<torusPrecision+1; i++)
		{
			vertices[ring*(torusPrecision+1)+i].position=vertices[i].position.GetRotatedY(ring*360.0f/torusPrecision);
			
			vertices[ring*(torusPrecision+1)+i].s=2.0f*ring/torusPrecision;
			vertices[ring*(torusPrecision+1)+i].t=vertices[i].t;

			vertices[ring*(torusPrecision+1)+i].sTangent=vertices[i].sTangent.GetRotatedY(ring*360.0f/torusPrecision);
			vertices[ring*(torusPrecision+1)+i].tTangent=vertices[i].tTangent.GetRotatedY(ring*360.0f/torusPrecision);
			vertices[ring*(torusPrecision+1)+i].normal=vertices[i].normal.GetRotatedY(ring*360.0f/torusPrecision);
		}
	}

	//calculate the indices
	for(int ring=0; ring<torusPrecision; ring++)
	{
		for(int i=0; i<torusPrecision; i++)
		{
			indices[((ring*torusPrecision+i)*2)*3+0]=ring*(torusPrecision+1)+i;
			indices[((ring*torusPrecision+i)*2)*3+1]=(ring+1)*(torusPrecision+1)+i;
			indices[((ring*torusPrecision+i)*2)*3+2]=ring*(torusPrecision+1)+i+1;
			indices[((ring*torusPrecision+i)*2+1)*3+0]=ring*(torusPrecision+1)+i+1;
			indices[((ring*torusPrecision+i)*2+1)*3+1]=(ring+1)*(torusPrecision+1)+i;
			indices[((ring*torusPrecision+i)*2+1)*3+2]=(ring+1)*(torusPrecision+1)+i+1;
		}
	}

	return true;
}
示例#28
0
bool SHADOW_MODEL::GenerateTorus(float innerRadius, float outerRadius)
{
	int torusPrecision=24;

	numVertices=(torusPrecision+1)*(torusPrecision+1);
	numIndices=2*torusPrecision*torusPrecision*3;
	numTriangles=numIndices/3;

	vertices=new SHADOW_MODEL_VERTEX[numVertices];
	if(!vertices)
	{
		errorLog.OutputError("Unable to allocate memory for torus vertices");
		return false;
	}

	indices=new unsigned int[numIndices];
	if(!indices)
	{
		errorLog.OutputError("Unable to allocate memory for torus indices");
		return false;
	}
	
	//calculate the first ring - inner radius 4, outer radius 1.5
	for(int i=0; i<torusPrecision+1; i++)
	{
		vertices[i].position=VECTOR3D(innerRadius, 0.0f, 0.0f).GetRotatedZ(i*360.0f/torusPrecision)+
									VECTOR3D(outerRadius, 0.0f, 0.0f);
		
		vertices[i].normal=VECTOR3D(0.0f, 0.0f, 1.0f).
							CrossProduct(VECTOR3D(0.0f, -1.0f, 0.0f).GetRotatedZ(i*360.0f/torusPrecision));
	}

	//rotate this to get other rings
	for(int ring=1; ring<torusPrecision+1; ring++)
	{
		for(int i=0; i<torusPrecision+1; i++)
		{
			vertices[ring*(torusPrecision+1)+i].position=vertices[i].position.GetRotatedY(ring*360.0f/torusPrecision);
			
			vertices[ring*(torusPrecision+1)+i].normal=vertices[i].normal.GetRotatedY(ring*360.0f/torusPrecision);
		}
	}

	//calculate the indices
	for(int ring=0; ring<torusPrecision; ring++)
	{
		for(int i=0; i<torusPrecision; i++)
		{
			indices[((ring*torusPrecision+i)*2)*3+0]=ring*(torusPrecision+1)+i;
			indices[((ring*torusPrecision+i)*2)*3+1]=(ring+1)*(torusPrecision+1)+i;
			indices[((ring*torusPrecision+i)*2)*3+2]=ring*(torusPrecision+1)+i+1;
			indices[((ring*torusPrecision+i)*2+1)*3+0]=ring*(torusPrecision+1)+i+1;
			indices[((ring*torusPrecision+i)*2+1)*3+1]=(ring+1)*(torusPrecision+1)+i;
			indices[((ring*torusPrecision+i)*2+1)*3+2]=(ring+1)*(torusPrecision+1)+i+1;
		}
	}


	//Calculate the plane equation for each face
	planeEquations=new PLANE[numTriangles];
	if(!planeEquations)
	{
		errorLog.OutputError("Unable to allocate memory for %d planes", numTriangles);
		return false;
	}

	for(unsigned int j=0; j<numTriangles; ++j)
	{
		planeEquations[j].SetFromPoints(vertices[indices[j*3+0]].position,
										vertices[indices[j*3+1]].position,
										vertices[indices[j*3+2]].position);
	}

	//Create space for the "is facing light" booleans
	isFacingLight=new bool[numTriangles];
	if(!isFacingLight)
	{
		errorLog.OutputError("Unable to allocate memory for %d booleans", numTriangles);
		return false;
	}

	//Create space for connectivity data
	neighbourIndices=new GLint[numTriangles*3];
	if(!neighbourIndices)
	{
		errorLog.OutputError("Unable to allocate memory for %d neighbour indices", numTriangles*3);
		return false;
	}

	//Create space for "is silhouette edge" booleans
	isSilhouetteEdge=new bool[numTriangles*3];
	if(!isSilhouetteEdge)
	{
		errorLog.OutputError("Unable to allocate memory for %d booleans", numTriangles*3);
		return false;
	}

	//Calculate the neighbours
	SetConnectivity();

	return true;
}
示例#29
0
//Tesselate a biquadratic patch
bool BSP_BIQUADRATIC_PATCH::Tesselate(int newTesselation)
{
	tesselation=newTesselation;

	float px, py;
	BSP_VERTEX temp[3];
	vertices=new BSP_VERTEX[(tesselation+1)*(tesselation+1)];

	for(int v=0; v<=tesselation; ++v)
	{
		px=(float)v/tesselation;

		vertices[v]=controlPoints[0]*((1.0f-px)*(1.0f-px))+
					controlPoints[3]*((1.0f-px)*px*2)+
					controlPoints[6]*(px*px);
	}

	for(int u=1; u<=tesselation; ++u)
	{
		py=(float)u/tesselation;

		temp[0]=controlPoints[0]*((1.0f-py)*(1.0f-py))+
				controlPoints[1]*((1.0f-py)*py*2)+
				controlPoints[2]*(py*py);

		temp[1]=controlPoints[3]*((1.0f-py)*(1.0f-py))+
				controlPoints[4]*((1.0f-py)*py*2)+
				controlPoints[5]*(py*py);

		temp[2]=controlPoints[6]*((1.0f-py)*(1.0f-py))+
				controlPoints[7]*((1.0f-py)*py*2)+
				controlPoints[8]*(py*py);

		for(int v=0; v<=tesselation; ++v)
		{
			px=(float)v/tesselation;

			vertices[u*(tesselation+1)+v]=	temp[0]*((1.0f-px)*(1.0f-px))+
											temp[1]*((1.0f-px)*px*2)+
											temp[2]*(px*px);
		}
	}

	//Create indices
	indices=new GLuint[tesselation*(tesselation+1)*2];
	if(!indices)
	{
		errorLog.OutputError("Unable to allocate memory for surface indices");
		return false;
	}

	for(int row=0; row<tesselation; ++row)
	{
		for(int point=0; point<=tesselation; ++point)
		{
			//calculate indices
			//reverse them to reverse winding
			indices[(row*(tesselation+1)+point)*2+1]=row*(tesselation+1)+point;
			indices[(row*(tesselation+1)+point)*2]=(row+1)*(tesselation+1)+point;
		}
	}


	//Fill in the arrays for multi_draw_arrays
	trianglesPerRow=new int[tesselation];
	rowIndexPointers=new unsigned int *[tesselation];
	if(!trianglesPerRow || !rowIndexPointers)
	{
		errorLog.OutputError("Unable to allocate memory for indices for multi_draw_arrays");
		return false;
	}

	for(int row=0; row<tesselation; ++row)
	{
		trianglesPerRow[row]=2*(tesselation+1);
		rowIndexPointers[row]=&indices[row*2*(tesselation+1)];
	}

	return true;
}
示例#30
0
///////////////////BSP::LoadLightmaps///////
////////////////////////////////////////////
bool BSP::LoadLightmaps(FILE * file)
{
	//Calculate number of lightmaps
	numLightmaps=header.directoryEntries[bspLightmaps].length/sizeof(BSP_LOAD_LIGHTMAP);

	//Create space for this many BSP_LOAD_LIGHTMAPs
	BSP_LOAD_LIGHTMAP * loadLightmaps=new BSP_LOAD_LIGHTMAP[numLightmaps];
	if(!loadLightmaps)
	{
		errorLog.OutputError("Unable to allocate space for %d BSP_LOAD_LIGHTMAPs", numLightmaps);
		return false;
	}

	//Load textures
	fseek(file, header.directoryEntries[bspLightmaps].offset, SEEK_SET);
	fread(loadLightmaps, 1, header.directoryEntries[bspLightmaps].length, file);

	//Create storage space for that many texture identifiers
	lightmapTextures=new GLuint[numLightmaps];
	if(!lightmapTextures)
	{
		errorLog.OutputError("Unable to create storage space for %d texture IDs", numLightmaps);
		return false;
	}
	
	//Generate the texture identifiers
	glGenTextures(numLightmaps, lightmapTextures);

	//Change the gamma settings on the lightmaps (make them brighter)
	float gamma=2.5f;
	for(int i=0; i<numLightmaps; ++i)
	{
		for(int j=0; j<128*128; ++j)
		{
			float r, g, b;
			r=loadLightmaps[i].lightmapData[j*3+0];
			g=loadLightmaps[i].lightmapData[j*3+1];
			b=loadLightmaps[i].lightmapData[j*3+2];

			r*=gamma/255.0f;
			g*=gamma/255.0f;
			b*=gamma/255.0f;

			//find the value to scale back up
			float scale=1.0f;
			float temp;
			if(r > 1.0f && (temp = (1.0f/r)) < scale) scale=temp;
			if(g > 1.0f && (temp = (1.0f/g)) < scale) scale=temp;
			if(b > 1.0f && (temp = (1.0f/b)) < scale) scale=temp;

			// scale up color values
			scale*=255.0f;		
			r*=scale;
			g*=scale;
			b*=scale;

			//fill data back in
			loadLightmaps[i].lightmapData[j*3+0]=(GLubyte)r;
			loadLightmaps[i].lightmapData[j*3+1]=(GLubyte)g;
			loadLightmaps[i].lightmapData[j*3+2]=(GLubyte)b;
		}
	}

	for(int i=0; i<numLightmaps; ++i)
	{
		glBindTexture(GL_TEXTURE_2D, lightmapTextures[i]);
		
		//Create texture
		gluBuild2DMipmaps(	GL_TEXTURE_2D, GL_RGBA8, 128, 128,
							GL_RGB, GL_UNSIGNED_BYTE, loadLightmaps[i].lightmapData);

		//Set Parameters
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	}

	//Create white texture for if no lightmap specified
	glGenTextures(1, &whiteTexture);
	glBindTexture(GL_TEXTURE_2D, whiteTexture);
	//Create texture
	gluBuild2DMipmaps(	GL_TEXTURE_2D, GL_RGBA8, 1, 1,
						GL_RGB, GL_FLOAT, white);
	//Set Parameters
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	if(loadLightmaps)
		delete [] loadLightmaps;
	loadLightmaps=NULL;

	return true;
}