From: ehofman Date: Sat, 12 Apr 2003 09:29:18 +0000 (+0000) Subject: Move the texture object to the screen directory for the sake of library dependencies X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=95c6c168514a8a9d769a1ca39cc8cedb5fa4969d;p=simgear.git Move the texture object to the screen directory for the sake of library dependencies --- diff --git a/simgear/misc/Makefile.am b/simgear/misc/Makefile.am index d961b03c..a3616de3 100644 --- a/simgear/misc/Makefile.am +++ b/simgear/misc/Makefile.am @@ -15,7 +15,6 @@ include_HEADERS = \ stopwatch.hxx \ strutils.hxx \ tabbed_values.hxx \ - texture.hxx \ texcoord.hxx \ zfstream.hxx @@ -28,7 +27,6 @@ libsgmisc_a_SOURCES = \ sgstream.cxx \ strutils.cxx \ tabbed_values.cxx \ - texture.cxx \ texcoord.cxx \ zfstream.cxx diff --git a/simgear/misc/texture.cxx b/simgear/misc/texture.cxx deleted file mode 100644 index b90f8635..00000000 --- a/simgear/misc/texture.cxx +++ /dev/null @@ -1,510 +0,0 @@ -/** - * \file texture.cxx - * Texture manipulation routines - * - * Copyright (c) Mark J. Kilgard, 1997. - * Code added in april 2003 by Erik Hofman - * - * This program is freely distributable without licensing fees - * and is provided without guarantee or warrantee expressed or - * implied. This program is -not- in the public domain. - * - * $Id$ - */ - -#include -#include - -#include "texture.hxx" -#include "colours.h" - -SGTexture::SGTexture() -{ - texture_data = 0; -} - -SGTexture::SGTexture(unsigned int width, unsigned int height) -{ - texture_data = new GLubyte[ width*height*3 ]; -} - -SGTexture::~SGTexture() -{ - delete texture_data; -} - -void -SGTexture::bind() -{ - if (!texture_data) { -#ifdef GL_VERSION_1_1 - glGenTextures(1, &texture_id); - -#elif GL_EXT_texture_object - glGenTexturesEXT(1, &texture_id); -#endif - } - -#ifdef GL_VERSION_1_1 - glBindTexture(GL_TEXTURE_2D, texture_id); - -#elif GL_EXT_texture_object - glBindTextureEXT(GL_TEXTURE_2D, texture_id); -#endif - - if (!texture_data) { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } -} - -/** - * A function to resize the OpenGL window which will be used by - * the dynamic texture generating routines. - * - * @param width The width of the new window - * @param height The height of the new window - */ -void -SGTexture::resize(unsigned int width, unsigned int height) -{ - GLfloat aspect; - - // Make sure that we don't get a divide by zero exception - if (height == 0) - height = 1; - - // Set the viewport for the OpenGL window - glViewport(0, 0, width, height); - - // Calculate the aspect ratio of the window - aspect = width/height; - - // Go to the projection matrix, this gets modified by the perspective - // calulations - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - - // Do the perspective calculations - gluPerspective(45.0, aspect, 1.0, 400.0); - - // Return to the modelview matrix - glMatrixMode(GL_MODELVIEW); -} - -/** - * A function to prepare the OpenGL state machine for dynamic - * texture generation. - * - * @param width The width of the texture - * @param height The height of the texture - */ -void -SGTexture::prepare(unsigned int width, unsigned int height) { - - texture_width = width; - texture_height = height; - - // Resize the OpenGL window to the size of our dynamic texture - resize(texture_width, texture_height); - - // Clear the contents of the screen buffer to blue - glClearColor(0.0, 0.0, 1.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // Turn off texturing (don't want the torus to be texture); - glDisable(GL_TEXTURE_2D); -} - -/** - * A function to generate the dynamic texture. - * - * The actual texture can be accessed by calling get_texture() - * - * @param width The width of the previous OpenGL window - * @param height The height of the previous OpenGL window - */ -void -SGTexture::finish(unsigned int width, unsigned int height) { - // If a texture hasn't been created then it gets created, and the contents - // of the frame buffer gets copied into it. If the texture has already been - // created then its contents just get updated. - bind(); - if (!texture_data) - { - // Copies the contents of the frame buffer into the texture - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, - texture_width, texture_height, 0); - - } else { - // Copies the contents of the frame buffer into the texture - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, - texture_width, texture_height); - } - - // Set the OpenGL window back to its previous size - resize(width, height); - - // Clear the window back to black - glClearColor(0.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -} - - -void -SGTexture::read_alpha_texture(const char *name) -{ - GLubyte *lptr; - SGTexture::ImageRec *image; - int y; - - if (texture_data) - delete texture_data; - - image = ImageOpen(name); - if(!image) { - return; - } - - texture_width = image->xsize; - texture_height = image->ysize; - - // printf("image->zsize = %d\n", image->zsize); - - if (image->zsize != 1) { - ImageClose(image); - return; - } - - texture_data = new GLubyte[ image->xsize * image->ysize ]; - if (!texture_data) - return; - - lptr = texture_data; - for(y=0; yysize; y++) { - ImageGetRow(image,lptr,y,0); - lptr += image->xsize; - } - ImageClose(image); -} - -void -SGTexture::read_rgb_texture(const char *name) -{ - GLubyte *ptr; - GLubyte *rbuf, *gbuf, *bbuf, *abuf; - SGTexture::ImageRec *image; - int y; - - if (texture_data) - delete texture_data; - - image = ImageOpen(name); - if(!image) - return; - - texture_width = image->xsize; - texture_height = image->ysize; - if (image->zsize != 3 && image->zsize != 4) { - ImageClose(image); - return; - } - - texture_data = new GLubyte[ image->xsize * image->ysize * 3]; - rbuf = new GLubyte[ image->xsize ]; - gbuf = new GLubyte[ image->xsize ]; - bbuf = new GLubyte[ image->xsize ]; - abuf = new GLubyte[ image->xsize ]; - if(!texture_data || !rbuf || !gbuf || !bbuf || !abuf) { - delete texture_data; - delete rbuf; - delete gbuf; - delete bbuf; - delete abuf; - return; - } - - ptr = texture_data; - for(y=0; yysize; y++) { - if(image->zsize == 4) { - ImageGetRow(image,rbuf,y,0); - ImageGetRow(image,gbuf,y,1); - ImageGetRow(image,bbuf,y,2); - ImageGetRow(image,abuf,y,3); /* Discard. */ - rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize); - ptr += (image->xsize * 3); - } else { - ImageGetRow(image,rbuf,y,0); - ImageGetRow(image,gbuf,y,1); - ImageGetRow(image,bbuf,y,2); - rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize); - ptr += (image->xsize * 3); - } - } - - ImageClose(image); - delete rbuf; - delete gbuf; - delete bbuf; - delete abuf; -} - -void -SGTexture::read_raw_texture(const char *name) -{ - GLubyte *ptr; - SGTexture::ImageRec *image; - int y; - - if (texture_data) - delete texture_data; - - image = RawImageOpen(name); - - if(!image) - return; - - texture_width = 256; - texture_height = 256; - - texture_data = new GLubyte[ 256 * 256 * 3 ]; - if(!texture_data) - return; - - ptr = texture_data; - for(y=0; y<256; y++) { - gzread(image->file, ptr, 256*3); - ptr+=256*3; - } - ImageClose(image); -} - -void -SGTexture::read_r8_texture(const char *name) -{ - unsigned char c[1]; - GLubyte *ptr; - SGTexture::ImageRec *image; - int xy; - - if (texture_data) - delete texture_data; - - //it wouldn't make sense to write a new function ... - image = RawImageOpen(name); - - if(!image) - return; - - texture_width = 256; - texture_height = 256; - - texture_data = new GLubyte [ 256 * 256 * 3 ]; - if(!texture_data) - return; - - ptr = texture_data; - for(xy=0; xy<(256*256); xy++) { - gzread(image->file, c, 1); - - //look in the table for the right colours - ptr[0]=msfs_colour[c[0]][0]; - ptr[1]=msfs_colour[c[0]][1]; - ptr[2]=msfs_colour[c[0]][2]; - - ptr+=3; - } - ImageClose(image); -} - - -SGTexture::ImageRec * -SGTexture::ImageOpen(const char *fileName) -{ - union { - int testWord; - char testByte[4]; - } endianTest; - - SGTexture::ImageRec *image; - int swapFlag; - int x; - - endianTest.testWord = 1; - if (endianTest.testByte[0] == 1) { - swapFlag = 1; - } else { - swapFlag = 0; - } - - image = new SGTexture::ImageRec; - if (image == 0) { - // fprintf(stderr, "Out of memory!\n"); - return 0; - } - if ((image->file = gzopen(fileName, "rb")) == 0) { - return 0; - } - - gzread(image->file, image, 12); - - if (swapFlag) { - ConvertShort(&image->imagic, 6); - } - - image->tmp = new GLubyte[ image->xsize * 256 ]; - if (image->tmp == 0) { - // fprintf(stderr, "\nOut of memory!\n"); - return 0; - } - - if ((image->type & 0xFF00) == 0x0100) { - x = image->ysize * image->zsize * (int) sizeof(unsigned); - image->rowStart = new unsigned[x]; - image->rowSize = new int[x]; - if (image->rowStart == 0 || image->rowSize == 0) { - // fprintf(stderr, "\nOut of memory!\n"); - return 0; - } - image->rleEnd = 512 + (2 * x); - gzseek(image->file, 512, SEEK_SET); - gzread(image->file, image->rowStart, x); - gzread(image->file, image->rowSize, x); - if (swapFlag) { - ConvertUint(image->rowStart, x/(int) sizeof(unsigned)); - ConvertUint((unsigned *)image->rowSize, x/(int) sizeof(int)); - } - } - return image; -} - - -void -SGTexture::ImageClose(SGTexture::ImageRec *image) { - gzclose(image->file); - delete image->tmp; - delete image; -} - - -SGTexture::ImageRec * -SGTexture::RawImageOpen(const char *fileName) -{ - union { - int testWord; - char testByte[4]; - } endianTest; - - SGTexture::ImageRec *image; - int swapFlag; - - endianTest.testWord = 1; - if (endianTest.testByte[0] == 1) { - swapFlag = 1; - } else { - swapFlag = 0; - } - - image = new SGTexture::ImageRec; - if (image == 0) { - // fprintf(stderr, "Out of memory!\n"); - return 0; - } - if ((image->file = gzopen(fileName, "rb")) == 0) { - return 0; - } - - gzread(image->file, image, 12); - - if (swapFlag) { - ConvertShort(&image->imagic, 6); - } - - - //just allocate a pseudo value as I'm too lazy to change ImageClose()... - image->tmp = new GLubyte; - - if (image->tmp == 0) { - // fprintf(stderr, "\nOut of memory!\n"); - return 0; - } - - return image; -} - -void -SGTexture::ImageGetRow(SGTexture::ImageRec *image, GLubyte *buf, int y, int z) { - GLubyte *iPtr, *oPtr, pixel; - int count; - - if ((image->type & 0xFF00) == 0x0100) { - gzseek(image->file, (long) image->rowStart[y+z*image->ysize], SEEK_SET); - gzread(image->file, image->tmp, - (unsigned int)image->rowSize[y+z*image->ysize]); - - iPtr = image->tmp; - oPtr = buf; - for (;;) { - pixel = *iPtr++; - count = (int)(pixel & 0x7F); - if (!count) { - return; - } - if (pixel & 0x80) { - while (count--) { - *oPtr++ = *iPtr++; - } - } else { - pixel = *iPtr++; - while (count--) { - *oPtr++ = pixel; - } - } - } - } else { - gzseek(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize), - SEEK_SET); - gzread(image->file, buf, image->xsize); - } -} - -void -SGTexture::rgbtorgb(GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *l, int n) { - while(n--) { - l[0] = r[0]; - l[1] = g[0]; - l[2] = b[0]; - l += 3; r++; g++; b++; - } -} - -void -SGTexture::ConvertShort(unsigned short *array, unsigned int length) { - unsigned short b1, b2; - unsigned char *ptr; - - ptr = (unsigned char *)array; - while (length--) { - b1 = *ptr++; - b2 = *ptr++; - *array++ = (b1 << 8) | (b2); - } -} - -void -SGTexture::ConvertUint(unsigned *array, unsigned int length) { - unsigned int b1, b2, b3, b4; - unsigned char *ptr; - - ptr = (unsigned char *)array; - while (length--) { - b1 = *ptr++; - b2 = *ptr++; - b3 = *ptr++; - b4 = *ptr++; - *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4); - } -} - diff --git a/simgear/misc/texture.hxx b/simgear/misc/texture.hxx deleted file mode 100644 index 908367c9..00000000 --- a/simgear/misc/texture.hxx +++ /dev/null @@ -1,80 +0,0 @@ - -#ifndef __SG_TEXTURE_HXX -#define __SG_TEXTURE_HXX 1 - -#include -#include - -class SGTexture { - -private: - - GLuint texture_id; - GLubyte *texture_data; - - GLsizei texture_width; - GLsizei texture_height; - - void resize(unsigned int width = 256, unsigned int height = 256); - -protected: - - typedef struct _ImageRec { - unsigned short imagic; - unsigned short type; - unsigned short dim; - unsigned short xsize, ysize, zsize; - unsigned int min, max; - unsigned int wasteBytes; - char name[80]; - unsigned long colorMap; - gzFile file; - GLubyte *tmp; - unsigned long rleEnd; - unsigned int *rowStart; - int *rowSize; - } ImageRec; - - void ConvertUint(unsigned *array, unsigned int length); - void ConvertShort(unsigned short *array, unsigned int length); - void rgbtorgb(GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *l, int n); - - ImageRec *ImageOpen(const char *fileName); - ImageRec *RawImageOpen(const char *fileName); - void ImageClose(ImageRec *image); - void ImageGetRow(ImageRec *image, GLubyte *buf, int y, int z); - -public: - - SGTexture(); - SGTexture(unsigned int width, unsigned int height); - ~SGTexture(); - - /* Copyright (c) Mark J. Kilgard, 1997. */ - void read_alpha_texture(const char *name); - void read_rgb_texture(const char *name); - void read_raw_texture(const char *name); - void read_r8_texture(const char *name); - - inline bool usable() { return texture_data ? true : false; } - - inline GLuint id() { return texture_id; } - inline GLubyte *texture() { return texture_data; } - - inline int width() { return texture_width; } - inline int height() { return texture_height; } - - void prepare(unsigned int width = 256, unsigned int height = 256); - void finish(unsigned int width, unsigned int height); - - void bind(); - inline void select() { - // if (texture_data) - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, - texture_width, texture_height, 0, - GL_RGB, GL_UNSIGNED_BYTE, texture_data ); - } -}; - -#endif - diff --git a/simgear/screen/Makefile.am b/simgear/screen/Makefile.am index aa16a1d8..5e8fe44b 100644 --- a/simgear/screen/Makefile.am +++ b/simgear/screen/Makefile.am @@ -12,9 +12,14 @@ IMAGE_SERVER_INCL = IMAGE_SERVER_SRCS = endif -include_HEADERS = $(IMAGE_SERVER_INCL) screen-dump.hxx tr.h +include_HEADERS = \ + texture.hxx \ + $(IMAGE_SERVER_INCL) \ + screen-dump.hxx \ + tr.h libsgscreen_a_SOURCES = \ + texture.cxx \ GLBitmaps.cxx GLBitmaps.h \ $(IMAGE_SERVER_SRCS) \ screen-dump.cxx \ diff --git a/simgear/screen/texture.cxx b/simgear/screen/texture.cxx new file mode 100644 index 00000000..764ede05 --- /dev/null +++ b/simgear/screen/texture.cxx @@ -0,0 +1,533 @@ +/** + * \file texture.cxx + * Texture manipulation routines + * + * Copyright (c) Mark J. Kilgard, 1997. + * Code added in april 2003 by Erik Hofman + * + * This program is freely distributable without licensing fees + * and is provided without guarantee or warrantee expressed or + * implied. This program is -not- in the public domain. + * + * $Id$ + */ + +#include +#include + +#include "texture.hxx" +#include "colours.h" + +SGTexture::SGTexture() +{ + texture_data = 0; +} + +SGTexture::SGTexture(unsigned int width, unsigned int height) +{ + texture_data = new GLubyte[ width * height * 3 ]; +} + +SGTexture::~SGTexture() +{ + delete texture_data; +} + +void +SGTexture::bind() +{ + if (!texture_data) { +#ifdef GL_VERSION_1_1 + glGenTextures(1, &texture_id); + +#elif GL_EXT_texture_object + glGenTexturesEXT(1, &texture_id); +#endif + } + +#ifdef GL_VERSION_1_1 + glBindTexture(GL_TEXTURE_2D, texture_id); + +#elif GL_EXT_texture_object + glBindTextureEXT(GL_TEXTURE_2D, texture_id); +#endif + + if (!texture_data) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } +} + +/** + * A function to resize the OpenGL window which will be used by + * the dynamic texture generating routines. + * + * @param width The width of the new window + * @param height The height of the new window + */ +void +SGTexture::resize(unsigned int width, unsigned int height) +{ + GLfloat aspect; + + // Make sure that we don't get a divide by zero exception + if (height == 0) + height = 1; + + // Set the viewport for the OpenGL window + glViewport(0, 0, width, height); + + // Calculate the aspect ratio of the window + aspect = width/height; + + // Go to the projection matrix, this gets modified by the perspective + // calulations + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + // Do the perspective calculations + gluPerspective(45.0, aspect, 1.0, 400.0); + + // Return to the modelview matrix + glMatrixMode(GL_MODELVIEW); +} + +/** + * A function to prepare the OpenGL state machine for dynamic + * texture generation. + * + * @param width The width of the texture + * @param height The height of the texture + */ +void +SGTexture::prepare(unsigned int width, unsigned int height) { + + texture_width = width; + texture_height = height; + + // Resize the OpenGL window to the size of our dynamic texture + resize(texture_width, texture_height); + + // Clear the contents of the screen buffer to blue + glClearColor(0.0, 0.0, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Turn off texturing (don't want the torus to be texture); + glDisable(GL_TEXTURE_2D); +} + +/** + * A function to generate the dynamic texture. + * + * The actual texture can be accessed by calling get_texture() + * + * @param width The width of the previous OpenGL window + * @param height The height of the previous OpenGL window + */ +void +SGTexture::finish(unsigned int width, unsigned int height) { + // If a texture hasn't been created then it gets created, and the contents + // of the frame buffer gets copied into it. If the texture has already been + // created then its contents just get updated. + bind(); + if (!texture_data) + { + // Copies the contents of the frame buffer into the texture + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, + texture_width, texture_height, 0); + + } else { + // Copies the contents of the frame buffer into the texture + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, + texture_width, texture_height); + } + + // Set the OpenGL window back to its previous size + resize(width, height); + + // Clear the window back to black + glClearColor(0.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + + +void +SGTexture::read_alpha_texture(const char *name) +{ + GLubyte *lptr; + SGTexture::ImageRec *image; + int y; + + if (texture_data) + delete texture_data; + + image = ImageOpen(name); + if(!image) { + return; + } + + texture_width = image->xsize; + texture_height = image->ysize; + + // printf("image->zsize = %d\n", image->zsize); + + if (image->zsize != 1) { + ImageClose(image); + return; + } + + texture_data = new GLubyte[ image->xsize * image->ysize ]; + if (!texture_data) + return; + + lptr = texture_data; + for(y=0; yysize; y++) { + ImageGetRow(image,lptr,y,0); + lptr += image->xsize; + } + ImageClose(image); +} + +void +SGTexture::read_rgb_texture(const char *name) +{ + GLubyte *ptr; + GLubyte *rbuf, *gbuf, *bbuf, *abuf; + SGTexture::ImageRec *image; + int y; + + if (texture_data) + delete texture_data; + + image = ImageOpen(name); + if(!image) + return; + + texture_width = image->xsize; + texture_height = image->ysize; + if (image->zsize != 3 && image->zsize != 4) { + ImageClose(image); + return; + } + + texture_data = new GLubyte[ image->xsize * image->ysize * 3]; + rbuf = new GLubyte[ image->xsize ]; + gbuf = new GLubyte[ image->xsize ]; + bbuf = new GLubyte[ image->xsize ]; + abuf = new GLubyte[ image->xsize ]; + if(!texture_data || !rbuf || !gbuf || !bbuf || !abuf) { + delete texture_data; + delete rbuf; + delete gbuf; + delete bbuf; + delete abuf; + return; + } + + ptr = texture_data; + for(y=0; yysize; y++) { + if(image->zsize == 4) { + ImageGetRow(image,rbuf,y,0); + ImageGetRow(image,gbuf,y,1); + ImageGetRow(image,bbuf,y,2); + ImageGetRow(image,abuf,y,3); /* Discard. */ + rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize); + ptr += (image->xsize * 3); + } else { + ImageGetRow(image,rbuf,y,0); + ImageGetRow(image,gbuf,y,1); + ImageGetRow(image,bbuf,y,2); + rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize); + ptr += (image->xsize * 3); + } + } + + ImageClose(image); + delete rbuf; + delete gbuf; + delete bbuf; + delete abuf; +} + +void +SGTexture::read_raw_texture(const char *name) +{ + GLubyte *ptr; + SGTexture::ImageRec *image; + int y; + + if (texture_data) + delete texture_data; + + image = RawImageOpen(name); + + if(!image) + return; + + texture_width = 256; + texture_height = 256; + + texture_data = new GLubyte[ 256 * 256 * 3 ]; + if(!texture_data) + return; + + ptr = texture_data; + for(y=0; y<256; y++) { + gzread(image->file, ptr, 256*3); + ptr+=256*3; + } + ImageClose(image); +} + +void +SGTexture::read_r8_texture(const char *name) +{ + unsigned char c[1]; + GLubyte *ptr; + SGTexture::ImageRec *image; + int xy; + + if (texture_data) + delete texture_data; + + //it wouldn't make sense to write a new function ... + image = RawImageOpen(name); + + if(!image) + return; + + texture_width = 256; + texture_height = 256; + + texture_data = new GLubyte [ 256 * 256 * 3 ]; + if(!texture_data) + return; + + ptr = texture_data; + for(xy=0; xy<(256*256); xy++) { + gzread(image->file, c, 1); + + //look in the table for the right colours + ptr[0]=msfs_colour[c[0]][0]; + ptr[1]=msfs_colour[c[0]][1]; + ptr[2]=msfs_colour[c[0]][2]; + + ptr+=3; + } + ImageClose(image); +} + + +void +SGTexture::set_pixel(GLuint x, GLuint y, sgVec3 &c) +{ + unsigned int pos = (x + y*texture_width)*3; + texture_data[pos] = c[0]; + texture_data[pos+1] = c[1]; + texture_data[pos+2] = c[2]; +} + + +sgVec3 * +SGTexture::get_pixel(GLuint x, GLuint y) +{ + static sgVec3 c; + unsigned int pos = (x + y*texture_width)*3; + + sgSetVec3(c, texture_data[pos], texture_data[pos+1], texture_data[pos+2]); + + return &c; +} + + +SGTexture::ImageRec * +SGTexture::ImageOpen(const char *fileName) +{ + union { + int testWord; + char testByte[4]; + } endianTest; + + SGTexture::ImageRec *image; + int swapFlag; + int x; + + endianTest.testWord = 1; + if (endianTest.testByte[0] == 1) { + swapFlag = 1; + } else { + swapFlag = 0; + } + + image = new SGTexture::ImageRec; + if (image == 0) { + // fprintf(stderr, "Out of memory!\n"); + return 0; + } + if ((image->file = gzopen(fileName, "rb")) == 0) { + return 0; + } + + gzread(image->file, image, 12); + + if (swapFlag) { + ConvertShort(&image->imagic, 6); + } + + image->tmp = new GLubyte[ image->xsize * 256 ]; + if (image->tmp == 0) { + // fprintf(stderr, "\nOut of memory!\n"); + return 0; + } + + if ((image->type & 0xFF00) == 0x0100) { + x = image->ysize * image->zsize * (int) sizeof(unsigned); + image->rowStart = new unsigned[x]; + image->rowSize = new int[x]; + if (image->rowStart == 0 || image->rowSize == 0) { + // fprintf(stderr, "\nOut of memory!\n"); + return 0; + } + image->rleEnd = 512 + (2 * x); + gzseek(image->file, 512, SEEK_SET); + gzread(image->file, image->rowStart, x); + gzread(image->file, image->rowSize, x); + if (swapFlag) { + ConvertUint(image->rowStart, x/(int) sizeof(unsigned)); + ConvertUint((unsigned *)image->rowSize, x/(int) sizeof(int)); + } + } + return image; +} + + +void +SGTexture::ImageClose(SGTexture::ImageRec *image) { + gzclose(image->file); + delete image->tmp; + delete image; +} + + +SGTexture::ImageRec * +SGTexture::RawImageOpen(const char *fileName) +{ + union { + int testWord; + char testByte[4]; + } endianTest; + + SGTexture::ImageRec *image; + int swapFlag; + + endianTest.testWord = 1; + if (endianTest.testByte[0] == 1) { + swapFlag = 1; + } else { + swapFlag = 0; + } + + image = new SGTexture::ImageRec; + if (image == 0) { + // fprintf(stderr, "Out of memory!\n"); + return 0; + } + if ((image->file = gzopen(fileName, "rb")) == 0) { + return 0; + } + + gzread(image->file, image, 12); + + if (swapFlag) { + ConvertShort(&image->imagic, 6); + } + + + //just allocate a pseudo value as I'm too lazy to change ImageClose()... + image->tmp = new GLubyte; + + if (image->tmp == 0) { + // fprintf(stderr, "\nOut of memory!\n"); + return 0; + } + + return image; +} + +void +SGTexture::ImageGetRow(SGTexture::ImageRec *image, GLubyte *buf, int y, int z) { + GLubyte *iPtr, *oPtr, pixel; + int count; + + if ((image->type & 0xFF00) == 0x0100) { + gzseek(image->file, (long) image->rowStart[y+z*image->ysize], SEEK_SET); + gzread(image->file, image->tmp, + (unsigned int)image->rowSize[y+z*image->ysize]); + + iPtr = image->tmp; + oPtr = buf; + for (;;) { + pixel = *iPtr++; + count = (int)(pixel & 0x7F); + if (!count) { + return; + } + if (pixel & 0x80) { + while (count--) { + *oPtr++ = *iPtr++; + } + } else { + pixel = *iPtr++; + while (count--) { + *oPtr++ = pixel; + } + } + } + } else { + gzseek(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize), + SEEK_SET); + gzread(image->file, buf, image->xsize); + } +} + +void +SGTexture::rgbtorgb(GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *l, int n) { + while(n--) { + l[0] = r[0]; + l[1] = g[0]; + l[2] = b[0]; + l += 3; r++; g++; b++; + } +} + +void +SGTexture::ConvertShort(unsigned short *array, unsigned int length) { + unsigned short b1, b2; + unsigned char *ptr; + + ptr = (unsigned char *)array; + while (length--) { + b1 = *ptr++; + b2 = *ptr++; + *array++ = (b1 << 8) | (b2); + } +} + + +void +SGTexture::ConvertUint(unsigned *array, unsigned int length) { + unsigned int b1, b2, b3, b4; + unsigned char *ptr; + + ptr = (unsigned char *)array; + while (length--) { + b1 = *ptr++; + b2 = *ptr++; + b3 = *ptr++; + b4 = *ptr++; + *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4); + } +} + diff --git a/simgear/screen/texture.hxx b/simgear/screen/texture.hxx new file mode 100644 index 00000000..2a1b5c5c --- /dev/null +++ b/simgear/screen/texture.hxx @@ -0,0 +1,90 @@ + +#ifndef __SG_TEXTURE_HXX +#define __SG_TEXTURE_HXX 1 + +#include +#include + +#include + +class SGTexture { + +private: + + GLuint texture_id; + GLubyte *texture_data; + + GLsizei texture_width; + GLsizei texture_height; + + void resize(unsigned int width = 256, unsigned int height = 256); + +protected: + + typedef struct _ImageRec { + unsigned short imagic; + unsigned short type; + unsigned short dim; + unsigned short xsize, ysize, zsize; + unsigned int min, max; + unsigned int wasteBytes; + char name[80]; + unsigned long colorMap; + gzFile file; + GLubyte *tmp; + unsigned long rleEnd; + unsigned int *rowStart; + int *rowSize; + } ImageRec; + + void ConvertUint(unsigned *array, unsigned int length); + void ConvertShort(unsigned short *array, unsigned int length); + void rgbtorgb(GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *l, int n); + + ImageRec *ImageOpen(const char *fileName); + ImageRec *RawImageOpen(const char *fileName); + void ImageClose(ImageRec *image); + void ImageGetRow(ImageRec *image, GLubyte *buf, int y, int z); + +public: + + SGTexture(); + SGTexture(unsigned int width, unsigned int height); + ~SGTexture(); + + /* Copyright (c) Mark J. Kilgard, 1997. */ + void read_alpha_texture(const char *name); + void read_rgb_texture(const char *name); + void read_raw_texture(const char *name); + void read_r8_texture(const char *name); + + inline bool usable() { return texture_data ? true : false; } + + inline GLuint id() { return texture_id; } + inline GLubyte *texture() { return texture_data; } + + inline int width() { return texture_width; } + inline int height() { return texture_height; } + + // dynamic texture functions. + // everything drawn to the OpenGL screen after prepare is + // called and before finish is called will be included + // in the new texture. + void prepare(unsigned int width = 256, unsigned int height = 256); + void finish(unsigned int width, unsigned int height); + + // texture pixel manipulation functions. + void set_pixel(GLuint x, GLuint y, sgVec3 &c); + sgVec3 *get_pixel(GLuint x, GLuint y); + + void bind(); + inline void select() { + // if (texture_data) + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, + texture_width, texture_height, 0, + GL_RGB, GL_UNSIGNED_BYTE, texture_data ); + } +}; + +#endif +