]> git.mxchange.org Git - flightgear.git/commitdiff
Move the texture code over from SimGear/simgear/screen
authorehofman <ehofman>
Mon, 22 Jun 2009 09:37:23 +0000 (09:37 +0000)
committerTim Moore <timoore@redhat.com>
Tue, 23 Jun 2009 08:54:10 +0000 (10:54 +0200)
utils/Modeller/Makefile.am
utils/Modeller/colours.h [new file with mode: 0644]
utils/Modeller/texture.cxx [new file with mode: 0644]
utils/Modeller/texture.hxx [new file with mode: 0644]

index 2d588757f1b6fb21a888c6ac7dbbc6c8966868f3..877fe39e9f69097dca2cb9f75cff4479dfe68910 100644 (file)
@@ -7,7 +7,7 @@ noinst_PROGRAMS = animassist normalmap photomodel
 animassist_SOURCES = animassist.c
 animassist_LDADD = $(base_LIBS)
 
-normalmap_SOURCES = normalmap.cxx
+normalmap_SOURCES = normalmap.cxx texture.cxx texture.hxx colours.h
 normalmap_LDADD = -lsgscreen $(opengl_LIBS) $(base_LIBS) -lz
 
 photomodel_SOURCES = photomodel.cxx
diff --git a/utils/Modeller/colours.h b/utils/Modeller/colours.h
new file mode 100644 (file)
index 0000000..acb5da7
--- /dev/null
@@ -0,0 +1,289 @@
+// colours.h -- This header file contains colour definitions in the
+//              same way as MS FS5 does
+//
+// Contributed by "Christian Mayer" <Vader@t-online.de>, started April 1999.
+//
+// Copyright (C) 1998  Christian Mayer - Vader@t-online.de
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+// $Id$
+
+
+#ifndef COLOURS_H
+#define COLOURS_H
+
+unsigned char msfs_colour[256][3]=
+{
+       {  0,   0,   0},
+       {  8,   8,   8},
+       { 16,  16,  16},
+       { 24,  24,  24},
+       { 32,  32,  32},
+       { 40,  40,  40},
+       { 48,  48,  48},
+       { 56,  56,  56},
+       { 65,  65,  65},
+       { 73,  73,  73},
+       { 81,  81,  81},
+       { 89,  89,  89},
+       { 97,  97,  97},
+       {105, 105, 105},
+       {113, 113, 113},
+       {121, 121, 121},
+       {130, 130, 130},
+       {138, 138, 138},
+       {146, 146, 146},
+       {154, 154, 154},
+       {162, 162, 162},
+       {170, 170, 170},
+       {178, 178, 178},
+       {186, 186, 186},
+       {195, 195, 195},
+       {203, 203, 203},
+       {211, 211, 211},
+       {219, 219, 219},
+       {227, 227, 227},
+       {235, 235, 235},
+       {247, 247, 247},
+       {255, 255, 255},
+       { 21,   5,   5}, 
+       { 42,  10,  10},
+       { 63,  15,  15},
+       { 84,  20,  20},
+       {105,  25,  25},
+       {126,  30,  30},
+       {147,  35,  35},
+       {168,  40,  40},
+       {189,  45,  45},
+       {210,  50,  50},
+       {231,  55,  55},
+       {252,  60,  60},
+       {  5,  21,   5},
+       { 10,  42,  10},
+       { 15,  63,  15},
+       { 20,  84,  20},
+       { 25, 105,  25},
+       { 30, 126,  30},
+       { 35, 147,  35},
+       { 40, 168,  40},
+       { 45, 189,  45},
+       { 50, 210,  50},
+       { 55, 231,  55},
+       { 60, 252,  60},
+       {  0,   7,  23},
+       {  0,  15,  40},
+       {  0,  23,  58},
+       {  0,  40,  84},
+       {  0,  64, 104},
+       {  0,  71, 122},
+       {  0,  87, 143},
+       {  0,  99, 156},
+       {  0, 112, 179},
+       {  0, 128, 199},
+       {  0, 143, 215},
+       {  0, 153, 230},
+       { 28,  14,   0},
+       { 56,  28,   0},
+       { 84,  42,   0},
+       {112,  56,   0},
+       {140,  70,   0},
+       {168,  84,   0},
+       {196,  98,   0},
+       {224, 112,   0},
+       {252, 126,   0},
+       { 28,  28,   0},
+       { 56,  56,   0},
+       { 84,  84,   0},
+       {112, 112,   0},
+       {140, 140,   0},
+       {168, 168,   0},
+       {196, 196,   0},
+       {224, 224,   0},
+       {252, 252,   0},
+       { 25,  21,  16},
+       { 50,  42,  32},
+       { 75,  63,  48},
+       {100,  84,  64},
+       {125, 105,  80},
+       {150, 126,  96},
+       {175, 147, 112},
+       {200, 168, 128},
+       {225, 189, 144},
+       { 28,  11,   7},
+       { 56,  22,  14},
+       { 84,  33,  21},
+       {112,  44,  28},
+       {140,  55,  35},
+       {168,  66,  42},
+       {196,  77,  49},
+       {224,  88,  56},
+       {252,  99,  63},
+       { 17,  22,   9},
+       { 34,  44,  18},
+       { 51,  66,  27},
+       { 68,  88,  36},
+       { 85, 110,  45},
+       {102, 132,  54},
+       {119, 154,  63},
+       {136, 176,  72},
+       {153, 198,  81},
+       {  0,  58, 104},
+       {  0,  87, 112},
+       { 43, 112, 128},
+       {255,   0,   0},
+       { 64, 255,  64},
+       {  0,   0, 192},
+       {  0, 105, 105},
+       {255, 128,   0},
+       {255, 255,   0},
+       { 81,  81,  81},
+       {121, 121, 121},
+       {146, 146, 146},
+       {170, 170, 170},
+       {195, 195, 195},
+       {227, 227, 227},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {  0,   0,   0},
+       {192, 192, 255},
+       {200, 200, 255},
+       {208, 208, 255},
+       {216, 216, 255},
+       {224, 224, 255},
+       {232, 232, 255},
+       {240, 240, 255},
+       {248, 248, 255},
+       {255, 255, 255},
+       {255, 255, 255},
+       {255, 255, 255},
+       {255, 255, 255},
+       {255, 255, 255},
+       {255, 255, 255},
+       {255, 255, 255},
+       {255, 255, 255},
+       { 16,  72,  16},
+       { 32,  80,  32},
+       { 48,  88,  48},
+       { 64,  96,  64},
+       { 80, 104,  80},
+       { 96, 112,  96},
+       {112, 120, 112},
+       {120, 124, 120},
+       {128, 128, 128},
+       {128, 128, 128},
+       {128, 128, 128},
+       {128, 128, 128},
+       {128, 128, 128},
+       {128, 128, 128},
+       {128, 128, 128},
+       {128, 128, 128},
+       { 33, 140, 189},
+       { 57, 132, 165},
+       {189,  66,  66},
+       {156,  66,  66},
+       {132,  74,  74},
+       { 33,  82, 107},
+       {214,  90,  82},
+       {189,  90,  82},
+       {165,  90,  82},
+       {123,  57,  49},
+       { 99,  57,  49},
+       {107,  74,  66},
+       {123,  90,  82},
+       {181,  90,  66},
+       { 74,  49,  41},
+       {189, 115,  90},
+       {140,  90,  49},
+       { 33,  49,  74},
+       {181, 115,  49},
+       { 99,  66,  33},
+       {165, 115,  66},
+       { 49,  41,  33},
+       {165, 140, 115},
+       {189, 165, 140},
+       { 57,  99, 123},
+       {181, 107,  24},
+       {206, 123,  33},
+       {156,  99,  33},
+       {148, 107,  49},
+       {107,  82,  49},
+       { 33,  33,  57},
+       { 33, 115, 165},
+       {214, 214,  33},
+       {173, 173,  33},
+       {198, 198,  41},
+       {140, 140,  33},
+       {115, 115,  33},
+       {189, 189,  57},
+       {156, 156,  49},
+       {173, 173,  57},
+       {123, 123,  49},
+       {123, 123,  66},
+       { 74,  74,  49},
+       {123, 123,  90},
+       { 41,  41,  33},
+       { 90,  99,  57},
+       {107, 115,  74},
+       {123, 148,  82},
+       {140, 173,  99},
+       {132, 156,  99},
+       { 49,  66,  41},
+       { 99, 165,  90},
+       { 74, 214,  74},
+       { 57, 140,  57},
+       { 74, 181,  74},
+       { 90, 198,  90},
+       { 57, 123,  57},
+       { 49,  99,  49},
+       { 90, 165,  90},
+       { 82, 148,  82},
+       { 74,  99,  74},
+       { 57, 115, 132},
+       { 33,  99, 123},
+       { 74, 115, 132}
+};
+
+
+#endif
diff --git a/utils/Modeller/texture.cxx b/utils/Modeller/texture.cxx
new file mode 100644 (file)
index 0000000..6f744c3
--- /dev/null
@@ -0,0 +1,964 @@
+/*
+ * 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 <simgear/compiler.h>
+
+#ifdef WIN32
+# include <windows.h>
+#endif
+
+#include <osg/GLU>
+
+#include <math.h>
+#include <zlib.h>
+
+#include "texture.hxx"
+#include "colours.h"
+
+
+const char *FILE_OPEN_ERROR = "Unable to open file.";
+const char *WRONG_COUNT = "Unsupported number of color channels.";
+const char *NO_TEXTURE = "No texture data resident.";
+const char *OUT_OF_MEMORY = "Out of memory.";
+
+
+SGTexture::SGTexture()
+   : texture_id(0),
+     texture_data(0),
+     num_colors(3),
+     file(0)
+{
+}
+
+SGTexture::SGTexture(unsigned int width, unsigned int height)
+   : texture_id(0),
+     errstr("")
+{
+    texture_data = new GLubyte[ width * height * 3 ];
+}
+
+SGTexture::~SGTexture()
+{
+    delete[] texture_data;
+
+    if ( texture_id != 0 ) {
+        free_id();
+    }
+}
+
+void
+SGTexture::bind()
+{
+    bool gen = false;
+    if (!texture_id) {
+#ifdef GL_VERSION_1_1
+        glGenTextures(1, &texture_id);
+
+#elif GL_EXT_texture_object
+        glGenTexturesEXT(1, &texture_id);
+#endif
+        gen = true;
+    }
+
+#ifdef GL_VERSION_1_1
+    glBindTexture(GL_TEXTURE_2D, texture_id);
+
+#elif GL_EXT_texture_object
+    glBindTextureEXT(GL_TEXTURE_2D, texture_id);
+#endif
+
+    if (gen) {
+        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);
+
+    glClearColor(0.0, 0.0, 0.0, 1.0);
+}
+
+/**
+ * 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;
+
+    delete[] texture_data;
+
+    image = ImageOpen(name);
+    if(!image) {
+        errstr = FILE_OPEN_ERROR;
+        return;
+    }
+
+    texture_width = image->xsize;
+    texture_height = image->ysize;
+
+    // printf("image->zsize = %d\n", image->zsize);
+
+    if (image->zsize != 1) {
+      ImageClose(image);
+      errstr = WRONG_COUNT;
+      return;
+    }
+
+    texture_data = new GLubyte[ image->xsize * image->ysize ];
+    num_colors = 1;
+    if (!texture_data) {
+        errstr = NO_TEXTURE;
+        return;
+    }
+
+    lptr = texture_data;
+    for(y=0; y<image->ysize; 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;
+    SGTexture::ImageRec *image;
+    int y;
+
+    delete[] texture_data;
+
+    image = ImageOpen(name);
+    if(!image) {
+        errstr = FILE_OPEN_ERROR;
+        return;
+    }
+
+    texture_width = image->xsize;
+    texture_height = image->ysize;
+    if (image->zsize < 1 || image->zsize > 4) {
+      ImageClose(image);
+      errstr = WRONG_COUNT;
+      return;
+    }
+
+    num_colors = 3;
+    texture_data = new GLubyte[ image->xsize * image->ysize * num_colors ];
+    rbuf = new GLubyte[ image->xsize ];
+    gbuf = new GLubyte[ image->xsize ];
+    bbuf = new GLubyte[ image->xsize ];
+    if(!texture_data || !rbuf || !gbuf || !bbuf) {
+      delete[] texture_data;
+      delete[] rbuf;
+      delete[] gbuf;
+      delete[] bbuf;
+      errstr = OUT_OF_MEMORY;
+      return;
+    }
+
+    ptr = texture_data;
+    for(y=0; y<image->ysize; y++) {
+        if(image->zsize == 4 || image->zsize == 3) {
+            ImageGetRow(image,rbuf,y,0);
+            ImageGetRow(image,gbuf,y,1);
+            ImageGetRow(image,bbuf,y,2);
+        } else {
+            ImageGetRow(image,rbuf,y,0);
+            memcpy(gbuf,rbuf,image->xsize);
+            memcpy(bbuf,rbuf,image->xsize);
+        }
+        rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize);
+        ptr += (image->xsize * num_colors);
+    }
+
+    ImageClose(image);
+    delete[] rbuf;
+    delete[] gbuf;
+    delete[] bbuf;
+}
+
+
+
+void
+SGTexture::read_rgba_texture(const char *name)
+{
+    GLubyte *ptr;
+    GLubyte *rbuf, *gbuf, *bbuf, *abuf;
+    SGTexture::ImageRec *image;
+    int y;
+
+    delete[] texture_data;
+
+    image = ImageOpen(name);
+    if(!image) {
+        errstr = FILE_OPEN_ERROR;
+        return;
+    }
+
+    texture_width = image->xsize;
+    texture_height = image->ysize;
+    if (image->zsize < 1 || image->zsize > 4) {
+      ImageClose(image);
+      errstr = WRONG_COUNT;
+      return;
+    }
+
+    num_colors = 4;
+    texture_data = new GLubyte[ image->xsize * image->ysize * num_colors ];
+    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;
+      errstr = OUT_OF_MEMORY;
+      return;
+    }
+
+    ptr = texture_data;
+    for(y=0; y<image->ysize; 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);
+        } else if(image->zsize == 3) {
+            ImageGetRow(image,rbuf,y,0);
+            ImageGetRow(image,gbuf,y,1);
+            ImageGetRow(image,bbuf,y,2);
+            memset(abuf, 255, image->xsize);
+        } else if(image->zsize == 2) {
+            ImageGetRow(image,rbuf,y,0);
+            memcpy(gbuf,rbuf,image->xsize);
+            memcpy(bbuf,rbuf,image->xsize);
+            ImageGetRow(image,abuf,y,1);
+        } else {
+            ImageGetRow(image,rbuf,y,0);
+            memcpy(gbuf,rbuf,image->xsize);
+            memcpy(bbuf,rbuf,image->xsize);
+            memset(abuf, 255, image->xsize);
+        }
+        rgbatorgba(rbuf,gbuf,bbuf,abuf,ptr,image->xsize);
+        ptr += (image->xsize * num_colors);
+    }
+
+    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;
+
+    delete[] texture_data;
+
+    image = RawImageOpen(name);
+
+    if(!image) {
+        errstr = FILE_OPEN_ERROR;
+        return;
+    }
+
+    texture_width = 256;
+    texture_height = 256;
+
+    texture_data = new GLubyte[ 256 * 256 * 3 ];
+    if(!texture_data) {
+      errstr = OUT_OF_MEMORY;
+      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;
+
+    delete[] texture_data;
+
+    //it wouldn't make sense to write a new function ...
+    image = RawImageOpen(name);
+
+    if(!image) {
+        errstr = FILE_OPEN_ERROR;
+        return;
+    }
+
+    texture_width = 256;
+    texture_height = 256;
+
+    texture_data = new GLubyte [ 256 * 256 * 3 ];
+    if(!texture_data) {
+        errstr = OUT_OF_MEMORY;
+        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::write_texture(const char *name) {
+   SGTexture::ImageRec *image = ImageWriteOpen(name);
+
+   for (int c=0; c<num_colors; c++) {
+      GLubyte *ptr = texture_data + c;
+      for (int y=0; y<texture_height; y++) {
+         for (int x=0; x<texture_width; x++) {
+           image->tmp[x]=*ptr;
+            ptr = ptr + num_colors;
+         }
+         fwrite(image->tmp, 1, texture_width, file);
+      }
+   }
+
+   ImageClose(image);
+}
+
+
+void
+SGTexture::set_pixel(GLuint x, GLuint y, GLubyte *c)
+{
+    if (!texture_data) {
+        errstr = NO_TEXTURE;
+        return;
+    }
+
+    unsigned int pos = (x + y*texture_width) * num_colors;
+    memcpy(texture_data+pos, c, num_colors);
+}
+
+
+GLubyte *
+SGTexture::get_pixel(GLuint x, GLuint y)
+{
+    static GLubyte c[4] = {0, 0, 0, 0};
+
+    if (!texture_data) {
+        errstr = NO_TEXTURE;
+        return c;
+    }
+
+    unsigned int pos = (x + y*texture_width)*num_colors;
+    memcpy(c, texture_data + pos, num_colors);
+
+    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;
+    memset(image, 0, sizeof(SGTexture::ImageRec));
+    if (image == 0) {
+        errstr = OUT_OF_MEMORY;
+        return 0;
+    }
+    if ((image->file = gzopen(fileName, "rb")) == 0) {
+      errstr = FILE_OPEN_ERROR;
+      return 0;
+    }
+
+    gzread(image->file, image, 12);
+
+    if (swapFlag) {
+        ConvertShort(&image->imagic, 6);
+    }
+
+    image->tmp = new GLubyte[ image->xsize * 256 ];
+    if (image->tmp == 0) {
+        errstr = OUT_OF_MEMORY;
+        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) {
+            errstr = OUT_OF_MEMORY;
+            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) {
+    if (image->file)  gzclose(image->file);
+    if (file) fclose(file);
+    delete[] image->tmp;
+    delete[] image->rowStart;
+    delete[] image->rowSize;
+    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;
+    memset(image, 0, sizeof(SGTexture::ImageRec));
+    if (image == 0) {
+        errstr = OUT_OF_MEMORY;
+        return 0;
+    }
+    if ((image->file = gzopen(fileName, "rb")) == 0) {
+      errstr = FILE_OPEN_ERROR;
+      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[1];
+
+    if (image->tmp == 0) {
+        errstr = OUT_OF_MEMORY;
+        return 0;
+    }
+
+    return image;
+}
+
+SGTexture::ImageRec *
+SGTexture::ImageWriteOpen(const char *fileName)
+{
+    union {
+        int testWord;
+        char testByte[4];
+    } endianTest;
+    ImageRec* image;
+    int swapFlag;
+    int x;
+
+    endianTest.testWord = 1;
+    if (endianTest.testByte[0] == 1) {
+        swapFlag = 1;
+    } else {
+        swapFlag = 0;
+    }
+
+    image = new SGTexture::ImageRec;
+    memset(image, 0, sizeof(SGTexture::ImageRec));
+    if (image == 0) {
+        errstr = OUT_OF_MEMORY;
+        return 0;
+    }
+    if ((file = fopen(fileName, "wb")) == 0) {
+        errstr = FILE_OPEN_ERROR;
+        return 0;
+    }
+
+    image->imagic = 474;
+    image->type = 0x0001;
+    image->dim = (num_colors > 1) ? 3 : 2;
+    image->xsize = texture_width;
+    image->ysize = texture_height;
+    image->zsize = num_colors;
+
+    if (swapFlag) {
+        ConvertShort(&image->imagic, 6);
+    }
+
+    fwrite(image, 1, 12, file);
+    fseek(file, 512, SEEK_SET);
+
+    image->tmp = new GLubyte[ image->xsize * 256 ];
+    if (image->tmp == 0) {
+        errstr = OUT_OF_MEMORY;
+        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) {
+            errstr = OUT_OF_MEMORY;
+            return 0;
+        }
+        image->rleEnd = 512 + (2 * x);
+        fseek(file, 512, SEEK_SET);
+        fread(image->rowStart, 1, x, file);
+        fread(image->rowSize, 1, x, file);
+        if (swapFlag) {
+            ConvertUint(image->rowStart, x/(int) sizeof(unsigned));
+            ConvertUint((unsigned *)image->rowSize, x/(int) sizeof(int));
+        }
+    }
+
+    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);
+        int size = image->rowSize[y+z*image->ysize];
+        gzread(image->file, image->tmp, size);
+
+        iPtr = image->tmp;
+        oPtr = buf;
+        for (GLubyte *limit = iPtr + size; iPtr < limit;) {
+            pixel = *iPtr++;
+            count = (int)(pixel & 0x7F);
+            if (!count) {
+                errstr = WRONG_COUNT;
+                return;
+            }
+            if (pixel & 0x80) {
+                while (iPtr < limit && count--) {
+                    *oPtr++ = *iPtr++;
+                }
+            } else if (iPtr < limit) {
+                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::ImagePutRow(SGTexture::ImageRec *image, GLubyte *buf, int y, int z) {
+    GLubyte *iPtr, *oPtr, pixel;
+    int count;
+
+    if ((image->type & 0xFF00) == 0x0100) {
+        fseek(file, (long) image->rowStart[y+z*image->ysize], SEEK_SET);
+        fread( image->tmp, 1, (unsigned int)image->rowSize[y+z*image->ysize],
+               file);
+
+        iPtr = image->tmp;
+        oPtr = buf;
+        for (;;) {
+            pixel = *iPtr++;
+            count = (int)(pixel & 0x7F);
+            if (!count) {
+                errstr = WRONG_COUNT;
+                return;
+            }
+            if (pixel & 0x80) {
+                while (count--) {
+                    *oPtr++ = *iPtr++;
+                }
+            } else {
+                pixel = *iPtr++;
+                while (count--) {
+                    *oPtr++ = pixel;
+                }
+            }
+        }
+    } else {
+        fseek(file, 512+(y*image->xsize)+(z*image->xsize*image->ysize),
+              SEEK_SET);
+        fread(buf, 1, image->xsize, file);
+    }
+}
+
+
+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::rgbatorgba(GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *a,
+                      GLubyte *l, int n) {
+    while(n--) {
+        l[0] = r[0];
+        l[1] = g[0];
+        l[2] = b[0];
+        l[3] = a[0];
+        l += 4; r++; g++; b++; a++;
+    }
+}
+
+
+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);
+    }
+}
+
+
+void
+SGTexture::make_monochrome(float contrast, GLubyte r, GLubyte g, GLubyte b) {
+
+   if (num_colors >= 3)
+      return;
+
+   GLubyte ap[3];
+   for (int y=0; y<texture_height; y++)
+      for (int x=0; x<texture_width; x++)
+      {
+         GLubyte *rgb = get_pixel(x,y);
+         GLubyte avg = (rgb[0] + rgb[1] + rgb[2]) / 3;
+
+         if (contrast != 1.0) {
+            float pixcol = -1.0 + (avg/128);
+            avg = 128 + int(128*pow(pixcol, contrast));
+         }
+
+         ap[0] = avg*r/255;
+         ap[1] = avg*g/255;
+         ap[2] = avg*b/255;
+
+         set_pixel(x,y,ap);
+      }
+}
+
+
+void
+SGTexture::make_grayscale(float contrast) {
+   if (num_colors < 3)
+      return;
+
+   int colors = (num_colors == 3) ? 1 : 2;
+   GLubyte *map = new GLubyte[ texture_width * texture_height * colors ];
+
+   for (int y=0; y<texture_height; y++)
+      for (int x=0; x<texture_width; x++)
+      {
+         GLubyte *rgb = get_pixel(x,y);
+         GLubyte avg = (rgb[0] + rgb[1] + rgb[2]) / 3;
+
+         if (contrast != 1.0) {
+            float pixcol = -1.0 + (avg/128);
+            avg = 128 + int(128*pow(pixcol, contrast));
+         }
+
+         int pos = (x + y*texture_width)*colors;
+         map[pos] = avg;
+         if (colors > 1)
+            map[pos+1] = rgb[3];
+      }
+
+   delete[] texture_data;
+   texture_data = map;
+   num_colors = colors;
+}
+
+
+void
+SGTexture::make_maxcolorwindow() {
+   GLubyte minmaxc[2] = {255, 0};
+
+   int pos = 0;
+   int max = num_colors;
+   if (num_colors == 2) max = 1;
+   if (num_colors == 4) max = 3; 
+   while (pos < texture_width * texture_height * num_colors) {
+      for (int i=0; i < max; i++) {
+         GLubyte c = texture_data[pos+i];
+         if (c < minmaxc[0]) minmaxc[0] = c;
+         if (c > minmaxc[1]) minmaxc[1] = c;
+      }
+      pos += num_colors;
+   }
+
+   GLubyte offs = minmaxc[0];
+   float factor = 255.0 / float(minmaxc[1] - minmaxc[0]);
+   // printf("Min: %i, Max: %i, Factor: %f\n", offs, minmaxc[1], factor);
+
+   pos = 0;
+   while (pos < texture_width * texture_height * num_colors) {
+      for (int i=0; i < max; i++) {
+         texture_data[pos+i] -= offs;
+         texture_data[pos+i] = int(factor * texture_data[pos+i]);
+      }
+      pos += num_colors;
+   }
+}
+
+
+void
+SGTexture::make_normalmap(float brightness, float contrast) {
+   make_grayscale(contrast);
+   make_maxcolorwindow();
+
+   int colors = (num_colors == 1) ? 3 : 4;
+   bool alpha = (colors > 3);
+   int tsize = texture_width * texture_height * colors;
+   GLubyte *map = new GLubyte[ tsize ];
+
+   int mpos = 0, dpos = 0;
+   for (int y=0; y<texture_height; y++) {
+      int ytw = y*texture_width;
+
+      for (int x=0; x<texture_width; x++)
+      {
+         int xp1 = (x < (texture_width-1)) ? x+1 : 0;
+         int yp1 = (y < (texture_height-1)) ? y+1 : 0;
+         int posxp1 = (xp1 + ytw)*num_colors;
+         int posyp1 = (x + yp1*texture_width)*num_colors;
+
+         GLubyte c = texture_data[dpos];
+         GLubyte cx1 = texture_data[posxp1];
+         GLubyte cy1 = texture_data[posyp1];
+
+         if (alpha) {
+            GLubyte a = texture_data[dpos+1];
+            GLubyte ax1 = texture_data[posxp1+1];
+            GLubyte ay1 = texture_data[posyp1+1];
+
+            c = (c + a)/2;
+            cx1 = (cx1 + ax1)/2;
+            cy1 = (cy1 + ay1)/2;
+
+            map[mpos+3] = a;
+         }
+
+         map[mpos+0] = (128+(cx1-c)/2);
+         map[mpos+1] = (128+(cy1-c)/2);
+         map[mpos+2] = 127+int(brightness*128); // 255-c/2;
+
+         mpos += colors;
+         dpos += num_colors;
+      }
+   }
+
+   delete[] texture_data;
+   texture_data = map;
+   num_colors = colors;
+}
+
+
+void
+SGTexture::make_bumpmap(float brightness, float contrast) {
+   make_grayscale(contrast);
+
+   int colors = (num_colors == 1) ? 1 : 2;
+   GLubyte *map = new GLubyte[ texture_width * texture_height * colors ];
+
+   for (int y=0; y<texture_height; y++)
+      for (int x=0; x<texture_width; x++)
+      {
+         int mpos = (x + y*texture_width)*colors;
+         int dpos = (x + y*texture_width)*num_colors;
+
+         int xp1 = (x < (texture_width-1)) ? x+1 : 0;
+         int yp1 = (y < (texture_height-1)) ? y+1 : 0;
+         int posxp1 = (xp1 + y*texture_width)*num_colors;
+         int posyp1 = (x + yp1*texture_width)*num_colors;
+
+         map[mpos] = (127 - ((texture_data[dpos]-texture_data[posxp1]) -
+                            ((texture_data[dpos]-texture_data[posyp1]))/4))/2;
+         if (colors > 1)
+            map[mpos+1] = texture_data[dpos+1];
+      }
+
+   delete[] texture_data;
+   texture_data = map;
+   num_colors = colors;
+}
+
diff --git a/utils/Modeller/texture.hxx b/utils/Modeller/texture.hxx
new file mode 100644 (file)
index 0000000..bdded36
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * \file texture.hxx
+ * 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.
+ */
+
+#ifndef __SG_TEXTURE_HXX
+#define __SG_TEXTURE_HXX 1
+
+#include <simgear/compiler.h>
+#include <osg/GL>
+#include <zlib.h>
+
+#include <plib/sg.h>
+
+/**
+ * A class to encapsulate all the info surrounding an OpenGL texture
+ * and also query various info and load various file formats
+ */
+class SGTexture {
+
+private:
+
+    GLuint texture_id;
+    GLubyte *texture_data;
+
+    GLsizei texture_width;
+    GLsizei texture_height;
+    GLsizei num_colors;
+
+    void resize(unsigned int width = 256, unsigned int height = 256);
+
+    const char *errstr;
+
+protected:
+
+    FILE *file;
+    typedef struct _ImageRec {
+        _ImageRec(void) : tmp(0), rowStart(0), rowSize(0) {}
+        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);
+    void rgbatorgba(GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *a,
+                    GLubyte *l, int n);
+
+    ImageRec *ImageOpen(const char *fileName);
+    ImageRec *ImageWriteOpen(const char *fileName);
+    ImageRec *RawImageOpen(const char *fileName);
+    void ImageClose(ImageRec *image);
+    void ImageGetRow(ImageRec *image, GLubyte *buf, int y, int z);
+    void ImagePutRow(ImageRec *image, GLubyte *buf, int y, int z);
+
+    inline void free_id() {
+#ifdef GL_VERSION_1_1
+        glDeleteTextures(1, &texture_id);
+#else
+        glDeleteTexturesEXT(1, &texture_id);
+#endif
+        texture_id = 0;
+    }
+
+
+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_rgba_texture(const char *name);
+    void read_raw_texture(const char *name);
+    void read_r8_texture(const char *name);
+    void write_texture(const char *name);
+
+    inline bool usable() { return (texture_id > 0) ? true : false; }
+
+    inline GLuint id() { return texture_id; }
+    inline GLubyte *texture() { return texture_data; }
+    inline void set_data(GLubyte *data) { texture_data = data; }
+    // inline void set_colors(int c) { num_colors = c; }
+
+    inline int width() { return texture_width; }
+    inline int height() { return texture_height; }
+    inline int colors() { return num_colors; }
+
+    // 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, GLubyte *c);
+    GLubyte *get_pixel(GLuint x, GLuint y);
+
+    void bind();
+    inline void select(bool keep_data = false) {
+        glTexImage2D( GL_TEXTURE_2D, 0, num_colors,
+                      texture_width, texture_height, 0,
+                      (num_colors==1)?GL_LUMINANCE:(num_colors==3)?GL_RGB:GL_RGBA, GL_UNSIGNED_BYTE, texture_data );
+
+        if (!keep_data) {
+            delete[] texture_data;
+            texture_data = 0;
+        }
+    }
+
+    // Nowhere does it say that resident textures have to be in video memory!
+    // NVidia's OpenGL drivers implement glAreTexturesResident() correctly,
+    // but the Matrox G400, for example, doesn't.
+    inline bool is_resident() {
+        GLboolean is_res;
+        glAreTexturesResident(1, &texture_id, &is_res);
+        return is_res != 0;
+    }
+
+    inline const char *err_str() { return errstr; }
+    inline void clear_err_str() { errstr = ""; }
+
+    void make_maxcolorwindow();
+    void make_grayscale(float contrast = 1.0);
+    void make_monochrome(float contrast = 1.0,
+                         GLubyte r=255, GLubyte g=255, GLubyte b=255);
+    void make_normalmap(float brightness = 1.0, float contrast = 1.0);
+    void make_bumpmap(float brightness = 1.0, float contrast = 1.0);
+};
+
+#endif
+