Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/importer/texture.cc @ 8316

Last change on this file since 8316 was 8316, checked in by bensch, 18 years ago

trunk: fixed most -Wall warnings… but there are still many missing :/

File size: 9.9 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14*/
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_IMPORTER
17
18#include "texture.h"
19
20#include "debug.h"
21#include "compiler.h"
22
23#ifdef HAVE_SDL_SDL_H
24#include <SDL/SDL_image.h>
25#include <SDL/SDL_endian.h>
26#include <SDL/SDL_byteorder.h>
27#else
28#include <SDL_endian.h>
29#include <SDL_image.h>
30#include <SDL_byteorder.h>
31#endif
32#if SDL_BYTEORDER == SDL_BIG_ENDIAN
33/*
34 * On the BIG_ENDIAN architecture, the 24 and 32bit bitmaps have
35 * different masks. If you don't do this distinction properly,
36 * you will get weird-looking textures.
37 */
38Uint32 alphaMask[] = {
39        0xFF000000,
40        0x00FF0000,
41        0x0000FF00,
42        0x000000FF,
43};
44
45Uint32 opaqueMask[] = {
46        0x00FF0000,
47        0x0000FF00,
48        0x000000FF,
49        0xFF000000
50};
51#else
52/*
53 * On the LIL_ENDIAN architecture everything is fine and easy. The 24
54 * and 32bit bitmaps have the same masks.
55 */
56Uint32 alphaMask[] = {
57        0x000000FF,
58        0x0000FF00,
59        0x00FF0000,
60        0xFF000000,
61};
62
63Uint32 *opaqueMask = alphaMask;
64
65#endif
66
67TextureData::TextureData()
68{
69  this->bAlpha = false;
70  this->texture = 0;
71  this->image = NULL;
72}
73
74
75/**
76 * @brief Destructor of a Texture
77 *
78 *  Frees Data, and deletes the textures from GL
79 */
80TextureData::~TextureData()
81{
82  if (this->texture != 0)
83    glDeleteTextures(1, &this->texture);
84  if (this->image != NULL)
85    SDL_FreeSurface(this->image);
86}
87
88
89/**
90 * @brief Loads an SDL_Surface.
91 */
92bool TextureData::loadSurface(SDL_Surface* surface, GLenum target)
93{
94  if (Texture::getTextureEnableState())
95  {
96    SDL_Surface* newSurf = Texture::prepareSurface(surface, this->bAlpha);
97    if (newSurf != NULL)
98    {
99      this->setSurface(newSurf);
100      this->setTexture(Texture::loadTexToGL(newSurf, target));
101      return true;
102    }
103  }
104  return false;
105}
106
107
108
109/**
110 * @brief set the surface this Texture handles
111 * @param newSurface the new Surface to set as the image for this Texture.
112 *
113 * This deletes the old version of the stored Texture,
114 * and sets the newly given Surface as current.
115 */
116bool TextureData::setSurface(SDL_Surface* newSurface)
117{
118  if (this->image != NULL)
119    SDL_FreeSurface(this->image);
120
121  this->image = newSurface;
122
123  return (this->image != NULL);
124}
125
126
127
128bool TextureData::setTexture(GLuint texture)
129{
130     // unload the old Texture.
131  if (this->texture != 0 && glIsTexture(this->getTexture()))
132  {
133    glDeleteTextures(1, &this->texture);
134  }
135  this->texture = texture;
136  return (texture != 0);
137}
138
139Texture::Texture()
140{
141  this->init();
142}
143
144
145Texture::Texture(const Texture& texture)
146  : data(texture.data)
147{
148  this->setClassID(CL_TEXTURE, "Texture");
149  this->priority = 0.5;
150}
151
152
153Texture::Texture(GLenum target, unsigned int width, unsigned int height, unsigned int channels, GLenum type)
154{
155  this->init();
156  GLuint texture = 0;
157  Texture::generateTexture(texture, target);
158
159  glBindTexture(target, texture);
160
161  unsigned int* pixels = new unsigned int[width * height * channels];
162  memset(pixels, 0, width * height * channels * sizeof(unsigned int));
163
164
165  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
166  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
167  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
168  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
169
170  glTexImage2D(target, 0, channels, width, height, 0, type, GL_UNSIGNED_INT, pixels);
171
172
173
174  delete[] pixels;
175
176  this->data->setTexture(texture);
177}
178
179/**
180 *  Constructor for a Texture
181 */
182Texture::Texture(const std::string& imageName, GLenum target)
183{
184  this->init();
185
186  if (!imageName.empty())
187  {
188    this->setName(imageName);
189    this->loadImage(imageName, target);
190  }
191}
192
193
194
195Texture::Texture(SDL_Surface* surface, GLenum target)
196{
197  this->init();
198
199  if(surface != NULL)
200  {
201    this->data->loadSurface(surface, target);
202  }
203}
204
205void Texture::init()
206{
207  this->setClassID(CL_TEXTURE, "Texture");
208
209  this->data = CountPointer<TextureData>(new TextureData());
210
211  this->priority = 0.5;
212}
213
214/**
215 * @brief Destructor of a Texture
216 *
217 * Frees Data, and deletes the textures from GL
218 */
219Texture::~Texture()
220{
221}
222
223
224/**
225 * @brief loads an Image from a file to a Texture
226 * @param imageName The image to load
227*/
228bool Texture::loadImage(const std::string& imageName, GLenum target)
229{
230  if (Texture::texturesEnabled)
231  {
232    if (!imageName.empty())
233    {
234      SDL_Surface* tmpSurf;
235
236      // load the new Image to memory
237      tmpSurf = IMG_Load(imageName.c_str());
238      if(tmpSurf != NULL)
239      {
240        this->data->loadSurface(tmpSurf, target);
241        SDL_FreeSurface(tmpSurf);
242        return true;
243      }
244      else
245      {
246        PRINTF(1)("IMG_Load: %s\n", IMG_GetError());
247        this->setTexture(0);
248        return false;
249      }
250    }
251    else
252    {
253      PRINTF(2)("Image-Name not specified\n");
254      return false;
255    }
256  }
257  return false;
258}
259
260/**
261 * @brief rebuilds the texture.
262 *
263 * reloads the Texture from Memory to OpenGL.
264 */
265bool Texture::rebuild()
266{
267  this->data->setTexture(0);
268
269  if (this->data->getStoredImage() != NULL)
270  {
271    PRINTF(3)("Reloading Texture of %s '%s'\n", this->getClassName(), this->getName());
272    this->setTexture(Texture::loadTexToGL(this->data->getStoredImage()));
273  }
274  return true;
275}
276
277bool Texture::texturesEnabled = true;
278
279/**
280 * @brief enables, disables textures
281 * @param texturesEnabled true if the textures should be enabled
282 */
283void Texture::setTextureEnableState(bool texturesEnabled)
284{
285  Texture::texturesEnabled = texturesEnabled;
286}
287
288
289//////////////////////////////////////
290// UTILITY FUNCTIONALITY OF TEXTURE //
291//////////////////////////////////////
292/**
293 * @brief converts surface to a new SDL_Surface, that is loadable by openGL
294 * @param surface the Surface to convert
295 * @param hasAlpha if the newly created Surface has an alpha channel, true is returned otherwise false.
296 * @returns a !!new!! Surface, that is loadable by openGL.
297 */
298SDL_Surface* Texture::prepareSurface(SDL_Surface* surface, bool& hasAlpha)
299{
300  assert(surface != NULL);
301  PRINTF(4)("Loading texture to OpenGL-Environment.\n");
302
303  SDL_Surface* retSurface;
304  SDL_Rect area;
305  Uint32 saved_flags;
306  Uint8  saved_alpha;
307  hasAlpha = false;
308  int pixelDepth = 24;
309
310        Uint32* mask = opaqueMask;
311
312  /* Save the alpha blending attributes */
313  saved_flags = surface->flags&(SDL_SRCALPHA | SDL_RLEACCELOK);
314  saved_alpha = surface->format->alpha;
315  if ( saved_flags & SDL_SRCALPHA )
316  {
317    SDL_SetAlpha(surface, 0, 0);
318    hasAlpha = true;
319    pixelDepth = 32;
320                mask = alphaMask;
321  }
322
323  retSurface = SDL_CreateRGBSurface(SDL_HWSURFACE,
324                                    surface->w, surface->h,
325                                    pixelDepth,
326                                                                                                                                                mask[0], mask[1], mask[2], mask[3] );
327  if ( retSurface == NULL )
328    return NULL;
329
330  /* Copy the surface into the GL texture this->data->getStoredImage() */
331  area.x = 0;
332  area.y = 0;
333  area.w = surface->w;
334  area.h = surface->h;
335  SDL_BlitSurface(surface, &area, retSurface, &area);
336
337  /* Restore the alpha blending attributes */
338  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA )
339  {
340    SDL_SetAlpha(surface, saved_flags | SDL_OPENGL, saved_alpha);
341    hasAlpha = true;
342  }
343
344  return (retSurface);
345}
346
347
348/**
349 * @brief Loads a Texture to the openGL-environment.
350 * @param surface the Image to load to openGL
351 * @returns The ID of the texture.
352 */
353GLuint Texture::loadTexToGL (const SDL_Surface* surface, GLenum target)
354{
355  //   if (this->data->getTexture() != 0 && glIsTexture(this->data->getTexture()))
356  //     glDeleteTextures(1, &this->data->getTexture());
357  //   this->data->getTexture() = 0;
358  assert(surface != NULL);
359
360  int      errorCode = 0;           //!< the error code for the texture loading functions
361  GLuint   texture = 0;             //!< the OpenGL texture handle
362  //int      mipmapLevel = 0;         //!< the maximum mipmap level for this texture
363  //int      mipmapWidth = 0;         //!< the width of the mipmap
364  //int      mipmapHight = 0;         //!< the height of the mipmap
365  GLenum   format = GL_RGB;
366  if (surface->format->BitsPerPixel == 32)
367  {
368    format = GL_RGBA;
369    assert(surface->format->BitsPerPixel == 32);
370  }
371  else
372  {
373    assert(surface->format->BitsPerPixel == 24);
374  }
375
376  /* Create an OpenGL texture for the this->data->getStoredImage() */
377  Texture::generateTexture(texture, target);
378
379//   glTexImage2D(target,  0,  format,
380//                surface->w,  surface->h,
381//                0, format,  GL_UNSIGNED_BYTE,
382//                surface->pixels);
383
384///  glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
385///  glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
386
387  /// TODO CHECK THIS BACK in
388  //glTexParameterf(GL_TEXTURE_ENV, GL_TEXTURE_PRIORITY, this->priority);
389
390  /* build the Texture  OpenGL V >= 1.1 */
391
392  //  printf("%s, w:%d h:%d, 0x%x\n", this->getName(), surface->w, surface->h, target);
393
394  /* control the mipmap levels */
395  glTexParameterf(GL_TEXTURE_ENV, GL_TEXTURE_MIN_LOD, 5);
396  glTexParameterf(GL_TEXTURE_ENV, GL_TEXTURE_MAX_LOD, 0);
397
398  // build the MipMaps automaticaly
399  errorCode = gluBuild2DMipmaps(target, format,
400                                surface->w,  surface->h,
401                                format,  GL_UNSIGNED_BYTE,
402                                surface->pixels
403                               );
404  if(unlikely(errorCode != 0))
405    PRINTF(1)("Error while loading texture (mipmap generation), gluBuild2DMipmaps returned %i\n", errorCode);
406
407  return texture;
408}
409
410void Texture::generateTexture(GLuint& texture, GLenum target)
411{
412  if (texture == 0 && !glIsTexture(texture))
413  {
414    glGenTextures(1, &texture);
415  }
416  glBindTexture(target, texture);
417
418  glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
419  glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
420
421  glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
422  glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
423
424}
Note: See TracBrowser for help on using the repository browser.