void WINDOW::Shutdown(void) //PROPERLY KILL WINDOW { //Delete font display lists glDeleteLists(base, 96); if (fullscreen) { ChangeDisplaySettings(NULL, 0); //restore desktop mode ShowCursor(TRUE); //show mouse cursor } errorLog.OutputNewline(); if(hRC) //have a rendering context? { if(!wglMakeCurrent(NULL, NULL)) //try to release rend cont { errorLog.OutputError("Release of DC and RC Failed."); } else errorLog.OutputSuccess("DC and RC released."); if(!wglDeleteContext(hRC)) //try to delete RC { errorLog.OutputError("Release Rendering Context Failed."); } else errorLog.OutputSuccess("Rendering Context Released."); hRC=NULL; //set RC to NULL } if(hDC && !ReleaseDC(hWnd, hDC)) //Are we able to release DC? { errorLog.OutputError("Release of Device Context Failed."); hDC=NULL; } else errorLog.OutputSuccess("Device Context Released."); if(hWnd && !DestroyWindow(hWnd)) //Can we destroy window? { errorLog.OutputError("Could not release hWnd"); hWnd=NULL; } else errorLog.OutputSuccess("hWnd released."); if (!UnregisterClass("OpenGL", hInstance)) //can we unreg. class? { errorLog.OutputError("Could Not Unregister Class."); hInstance=NULL; } else errorLog.OutputSuccess("Class unregistered."); }
///////////////////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; }
//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; }
//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; }
bool PBUFFER::MakeCurrent() { if(!wglMakeCurrent(hDC, hRC)) { errorLog.OutputError("Unable to change current context"); return false; } return true; }
//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; }
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; }
//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 }
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"); } }
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; }
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; }
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; }
//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; }
//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; }
//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; }
void WINDOW::SaveScreenshot(void) { FILE * file; //first calculate the filename to save to char filename[32]; for(int i=0; i<1000; i++) { sprintf(filename, "screen%03d.tga", i); //try opening this file - if not possible, use this filename file=fopen(filename, "rb"); if(!file) { break; } //otherwise, the file exists, try next, except if this is the last one fclose(file); if(i==999) { errorLog.OutputError("No space to save screenshot - 0-999 exist"); return; } } errorLog.OutputSuccess("Saving %s", filename); GLubyte TGAheader[12]={0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //Uncompressed TGA header GLubyte infoHeader[6]; unsigned char * data=new unsigned char[4*width*height]; if(!data) { errorLog.OutputError("Unable to allocate memory for screen data"); return; } //read in the screen data glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); //data needs to be in BGR format //swap b and r for(int i=0; i<(int)width*height*4; i+=4) { //repeated XOR to swap bytes 0 and 2 data[i] ^= data[i+2] ^= data[i] ^= data[i+2]; } //open the file file = fopen(filename, "wb"); //save header fwrite(TGAheader, 1, sizeof(TGAheader), file); //save info header infoHeader[0]=(width & 0x00FF); infoHeader[1]=(width & 0xFF00) >> 8; infoHeader[2]=(height & 0x00FF); infoHeader[3]=(height & 0xFF00) >> 8; infoHeader[4]=32; infoHeader[5]=0; //save info header fwrite(infoHeader, 1, sizeof(infoHeader), file); //save the image data fwrite(data, 1, width*height*4, file); fclose(file); errorLog.OutputSuccess("Saved Screenshot: %s", filename); return; }
//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; }
////////////////////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; }
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; }
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! }
//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; }
//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; }
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; }
///////////////////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; }
///////////////////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; }
//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; }
//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; }
bool SetUpNV_vertex_program() { //Check for support char * extensionString=(char *)glGetString(GL_EXTENSIONS); char * extensionName="GL_NV_vertex_program"; 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)) { NV_vertex_program_supported=true; } //if not, move on extensionString+=distanceToSpace+1; } if(!NV_vertex_program_supported) { errorLog.OutputError("NV_vertex_program unsupported!"); return false; } errorLog.OutputSuccess("NV_vertex_program supported!"); //get function pointers glBindProgramNV = (PFNGLBINDPROGRAMNVPROC) wglGetProcAddress("glBindProgramNV"); glDeleteProgramsNV = (PFNGLDELETEPROGRAMSNVPROC) wglGetProcAddress("glDeleteProgramsNV"); glExecuteProgramNV = (PFNGLEXECUTEPROGRAMNVPROC) wglGetProcAddress("glExecuteProgramNV"); glGenProgramsNV = (PFNGLGENPROGRAMSNVPROC) wglGetProcAddress("glGenProgramsNV"); glAreProgramsResidentNV = (PFNGLAREPROGRAMSRESIDENTNVPROC) wglGetProcAddress("glAreProgramsResidentNV"); glRequestResidentProgramsNV = (PFNGLREQUESTRESIDENTPROGRAMSNVPROC) wglGetProcAddress("glRequestResidentProgramsNV"); glGetProgramParameterfvNV = (PFNGLGETPROGRAMPARAMETERFVNVPROC) wglGetProcAddress("glGetProgramParameterfvNV"); glGetProgramParameterdvNV = (PFNGLGETPROGRAMPARAMETERDVNVPROC) wglGetProcAddress("glGetProgramParameterdvNV"); glGetProgramivNV = (PFNGLGETPROGRAMIVNVPROC) wglGetProcAddress("glGetProgramivNV"); glGetProgramStringNV = (PFNGLGETPROGRAMSTRINGNVPROC) wglGetProcAddress("glGetProgramStringNV"); glGetTrackMatrixivNV = (PFNGLGETTRACKMATRIXIVNVPROC) wglGetProcAddress("glGetTrackMatrixivNV"); glGetVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) wglGetProcAddress("glGetVertexAttribdvNV"); glGetVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) wglGetProcAddress("glGetVertexAttribfvNV"); glGetVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) wglGetProcAddress("glGetVertexAttribivNV"); glGetVertexAttribPointervNV = (PFNGLGETVERTEXATTRIBPOINTERVNVPROC) wglGetProcAddress("glGetVertexAttribPointervNV"); glIsProgramNV = (PFNGLISPROGRAMNVPROC) wglGetProcAddress("glIsProgramNV"); glLoadProgramNV = (PFNGLLOADPROGRAMNVPROC) wglGetProcAddress("glLoadProgramNV"); glProgramParameter4fNV = (PFNGLPROGRAMPARAMETER4FNVPROC) wglGetProcAddress("glProgramParameter4fNV"); glProgramParameter4dNV = (PFNGLPROGRAMPARAMETER4DNVPROC) wglGetProcAddress("glProgramParameter4dNV"); glProgramParameter4fvNV = (PFNGLPROGRAMPARAMETER4FVNVPROC) wglGetProcAddress("glProgramParameter4fvNV"); glProgramParameter4dvNV = (PFNGLPROGRAMPARAMETER4DVNVPROC) wglGetProcAddress("glProgramParameter4dvNV"); glProgramParameters4fvNV = (PFNGLPROGRAMPARAMETERS4FVNVPROC) wglGetProcAddress("glProgramParameters4fvNV"); glProgramParameters4dvNV = (PFNGLPROGRAMPARAMETERS4DVNVPROC) wglGetProcAddress("glProgramParameters4dvNV"); glTrackMatrixNV = (PFNGLTRACKMATRIXNVPROC) wglGetProcAddress("glTrackMatrixNV"); glVertexAttribPointerNV = (PFNGLVERTEXATTRIBPOINTERNVPROC) wglGetProcAddress("glVertexAttribPointerNV"); glVertexAttrib1sNV = (PFNGLVERTEXATTRIB1SNVPROC) wglGetProcAddress("glVertexAttrib1sNV"); glVertexAttrib1fNV = (PFNGLVERTEXATTRIB1FNVPROC) wglGetProcAddress("glVertexAttrib1fNV"); glVertexAttrib1dNV = (PFNGLVERTEXATTRIB1DNVPROC) wglGetProcAddress("glVertexAttrib1dNV"); glVertexAttrib2sNV = (PFNGLVERTEXATTRIB2SNVPROC) wglGetProcAddress("glVertexAttrib2sNV"); glVertexAttrib2fNV = (PFNGLVERTEXATTRIB2FNVPROC) wglGetProcAddress("glVertexAttrib2fNV"); glVertexAttrib2dNV = (PFNGLVERTEXATTRIB2DNVPROC) wglGetProcAddress("glVertexAttrib2dNV"); glVertexAttrib3sNV = (PFNGLVERTEXATTRIB3SNVPROC) wglGetProcAddress("glVertexAttrib3sNV"); glVertexAttrib3fNV = (PFNGLVERTEXATTRIB3FNVPROC) wglGetProcAddress("glVertexAttrib3fNV"); glVertexAttrib3dNV = (PFNGLVERTEXATTRIB3DNVPROC) wglGetProcAddress("glVertexAttrib3dNV"); glVertexAttrib4sNV = (PFNGLVERTEXATTRIB4SNVPROC) wglGetProcAddress("glVertexAttrib4sNV"); glVertexAttrib4fNV = (PFNGLVERTEXATTRIB4FNVPROC) wglGetProcAddress("glVertexAttrib4fNV"); glVertexAttrib4dNV = (PFNGLVERTEXATTRIB4DNVPROC) wglGetProcAddress("glVertexAttrib4dNV"); glVertexAttrib4ubNV = (PFNGLVERTEXATTRIB4UBNVPROC) wglGetProcAddress("glVertexAttrib4ubNV"); glVertexAttrib1svNV = (PFNGLVERTEXATTRIB1SVNVPROC) wglGetProcAddress("glVertexAttrib1svNV"); glVertexAttrib1fvNV = (PFNGLVERTEXATTRIB1FVNVPROC) wglGetProcAddress("glVertexAttrib1fvNV"); glVertexAttrib1dvNV = (PFNGLVERTEXATTRIB1DVNVPROC) wglGetProcAddress("glVertexAttrib1dvNV"); glVertexAttrib2svNV = (PFNGLVERTEXATTRIB2SVNVPROC) wglGetProcAddress("glVertexAttrib2svNV"); glVertexAttrib2fvNV = (PFNGLVERTEXATTRIB2FVNVPROC) wglGetProcAddress("glVertexAttrib2fvNV"); glVertexAttrib2dvNV = (PFNGLVERTEXATTRIB2DVNVPROC) wglGetProcAddress("glVertexAttrib2dvNV"); glVertexAttrib3svNV = (PFNGLVERTEXATTRIB3SVNVPROC) wglGetProcAddress("glVertexAttrib3svNV"); glVertexAttrib3fvNV = (PFNGLVERTEXATTRIB3FVNVPROC) wglGetProcAddress("glVertexAttrib3fvNV"); glVertexAttrib3dvNV = (PFNGLVERTEXATTRIB3DVNVPROC) wglGetProcAddress("glVertexAttrib3dvNV"); glVertexAttrib4svNV = (PFNGLVERTEXATTRIB4SVNVPROC) wglGetProcAddress("glVertexAttrib4svNV"); glVertexAttrib4fvNV = (PFNGLVERTEXATTRIB4FVNVPROC) wglGetProcAddress("glVertexAttrib4fvNV"); glVertexAttrib4dvNV = (PFNGLVERTEXATTRIB4DVNVPROC) wglGetProcAddress("glVertexAttrib4dvNV"); glVertexAttrib4ubvNV = (PFNGLVERTEXATTRIB4UBVNVPROC) wglGetProcAddress("glVertexAttrib4ubvNV"); glVertexAttribs1svNV = (PFNGLVERTEXATTRIBS1SVNVPROC) wglGetProcAddress("glVertexAttribs1svNV"); glVertexAttribs1fvNV = (PFNGLVERTEXATTRIBS1FVNVPROC) wglGetProcAddress("glVertexAttribs1fvNV"); glVertexAttribs1dvNV = (PFNGLVERTEXATTRIBS1DVNVPROC) wglGetProcAddress("glVertexAttribs1dvNV"); glVertexAttribs2svNV = (PFNGLVERTEXATTRIBS2SVNVPROC) wglGetProcAddress("glVertexAttribs2svNV"); glVertexAttribs2fvNV = (PFNGLVERTEXATTRIBS2FVNVPROC) wglGetProcAddress("glVertexAttribs2fvNV"); glVertexAttribs2dvNV = (PFNGLVERTEXATTRIBS2DVNVPROC) wglGetProcAddress("glVertexAttribs2dvNV"); glVertexAttribs3svNV = (PFNGLVERTEXATTRIBS3SVNVPROC) wglGetProcAddress("glVertexAttribs3svNV"); glVertexAttribs3fvNV = (PFNGLVERTEXATTRIBS3FVNVPROC) wglGetProcAddress("glVertexAttribs3fvNV"); glVertexAttribs3dvNV = (PFNGLVERTEXATTRIBS3DVNVPROC) wglGetProcAddress("glVertexAttribs3dvNV"); glVertexAttribs4svNV = (PFNGLVERTEXATTRIBS4SVNVPROC) wglGetProcAddress("glVertexAttribs4svNV"); glVertexAttribs4fvNV = (PFNGLVERTEXATTRIBS4FVNVPROC) wglGetProcAddress("glVertexAttribs4fvNV"); glVertexAttribs4dvNV = (PFNGLVERTEXATTRIBS4DVNVPROC) wglGetProcAddress("glVertexAttribs4dvNV"); glVertexAttribs4ubvNV = (PFNGLVERTEXATTRIBS4UBVNVPROC) wglGetProcAddress("glVertexAttribs4ubvNV"); return true; }
///////////////////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; }
///////////////////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; }