Skip to content
Snippets Groups Projects
Select Git revision
  • 0699333bfe5525e72209e2a1d1fb5ecc83746a86
  • master default protected
  • 2018ws
  • 2017ws
  • 2016ws
5 results

textured-spheres.c

Blame
  • Forked from Peter Gerwinski / hp
    267 commits behind the upstream repository.
    textured-spheres.c 4.68 KiB
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/stat.h>
    #include <png.h>
    #include "textured-spheres.h"
    
    #ifndef __USE_POSIX
      extern int fileno (FILE *stream);
    #endif
    
    static png_byte *load_png_file (char *filename, unsigned *w, unsigned *h)
    {
      FILE *f = fopen (filename, "rb");
      if (!f)
        return NULL;
    
      /* is it a PNG file? */
      png_byte buf[8];
      if (fread (buf, 1, 8, f) != 8)
        {
          fclose (f);
          return NULL;
        }
      if (!png_check_sig (buf, 8))
        {
          fclose (f);
          return NULL;
        }
    
      png_struct *png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
                                                    NULL, NULL, NULL);
      if (!png_ptr)
        {
          fclose (f);
          return NULL;
        }
    
      png_info *info_ptr = png_create_info_struct (png_ptr);
      if (!info_ptr)
        {
          fclose (f);
          png_destroy_read_struct (&png_ptr, NULL, NULL);
          return NULL;
        }
    
      if (setjmp (png_jmpbuf (png_ptr)))
        {
          fclose (f);
          png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
          return NULL;
        }
    
      png_init_io (png_ptr, f);
      png_set_sig_bytes (png_ptr, 8);
      png_read_info (png_ptr, info_ptr);
    
      png_uint_32 width;
      png_uint_32 height;
      int bit_depth;
      int color_type;
      png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth,
                    &color_type, NULL, NULL, NULL);
    
      /* tell libpng to strip 16 bit/color files down to 8 bits/color */
      if (bit_depth == 16)
        png_set_strip_16 (png_ptr);
      /* expand paletted colors into true RGB triplets */
      if (color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_expand (png_ptr);
      /* expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
      if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
        png_set_expand (png_ptr);
      /* expand paletted or RGB images with transparency to full alpha channels
         so the data will be available as RGBA quartets. */
      if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_expand (png_ptr);
      /* transform grayscale images into rgb */
      if (color_type == PNG_COLOR_TYPE_GRAY
          || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb (png_ptr);
    
      if (color_type & PNG_COLOR_MASK_ALPHA)
        png_set_strip_alpha (png_ptr);
    
      png_read_update_info (png_ptr, info_ptr);
      png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth,
    		&color_type, NULL, NULL, NULL);
      if (color_type != PNG_COLOR_TYPE_RGB
          && color_type != PNG_COLOR_TYPE_RGB_ALPHA)
        {
          fclose (f);
          png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
          return NULL;
        }
    
      png_uint_32 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
      if (row_bytes & 0x01)
        row_bytes++;
    
      png_byte *png_pixels = malloc (row_bytes * height * sizeof (png_byte));
      if (png_pixels == NULL)
        {
          fclose (f);
          png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
          return NULL;
        }
    
      png_byte **row_pointers = malloc (height * sizeof (png_bytep));
      if (row_pointers == NULL)
        {
          fclose (f);
          png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
          free (png_pixels);
          png_pixels = NULL;
          return NULL;
        }
    
      int i;
      for (i = 0; i < height; i++)
        row_pointers[i] = png_pixels + i * row_bytes;
    
      png_read_image (png_ptr, row_pointers);
    
      png_read_end (png_ptr, info_ptr);
      png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
      fclose (f);
    
      if (w)
        *w = width;
      if (h)
        *h = height;
      free (row_pointers);
    
      return png_pixels;
    }
    
    void init_texture (char *image_filename, GLuint *texture)
    {
      unsigned image_width, image_height;
      png_byte *image = load_png_file (image_filename, &image_width, &image_height);
      if (!image)
        {
          fprintf (stderr, "textured-spheres.c: cannot open texture file \"%s\"",
                   image_filename);
          exit (1);
        }
      glGenTextures (1, texture);
      glBindTexture (GL_TEXTURE_2D, *texture);
      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
      glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
      gluBuild2DMipmaps (GL_TEXTURE_2D, 3, image_width, image_height, GL_RGB, GL_UNSIGNED_BYTE, image);
    }
    
    void draw_textured_sphere (GLuint texture, GLdouble radius, GLint slices, GLint stacks)
    {
      static GLfloat white_color[] = { 1.0, 1.0, 1.0 };
      glMaterialfv (GL_FRONT, GL_AMBIENT, white_color);
      glMaterialfv (GL_FRONT, GL_DIFFUSE, white_color);
      glBindTexture (GL_TEXTURE_2D, texture);
      glEnable (GL_TEXTURE_2D);
      GLUquadric *sphere = gluNewQuadric ();
      gluQuadricTexture (sphere, GL_TRUE);
      gluSphere (sphere, radius, slices, stacks);
      glDisable (GL_TEXTURE_2D);
    }