Преглед на файлове

per corner normals, texture mapping

Former-commit-id: 947bfa332dc07d778eb012e986d627a8288295a5
jalec преди 13 години
родител
ревизия
9f4b4acd36
променени са 5 файла, в които са добавени 843 реда и са изтрити 5 реда
  1. 3 0
      PI.h
  2. 102 0
      per_corner_normals.h
  3. 85 0
      texture_from_tga.h
  4. 648 0
      tga.h
  5. 5 5
      writeMESH.h

+ 3 - 0
PI.h

@@ -1,3 +1,5 @@
+#ifndef IGL_PI_H
+#define IGL_PI_H
 namespace igl
 {
   // Use standard mathematical constants' M_PI if available
@@ -7,3 +9,4 @@ namespace igl
   const double PI = 3.1415926535897932384626433832795;
 #endif
 }
+#endif

+ 102 - 0
per_corner_normals.h

@@ -0,0 +1,102 @@
+#ifndef IGL_PER_CORNER_NORMALS_H
+#define IGL_PER_CORNER_NORMALS_H
+#include <Eigen/Core>
+#endif
+
+namespace igl
+{
+  // Compute vertex normals via vertex position list, face list
+  // Inputs:
+  //   V  #V by 3 eigen Matrix of mesh vertex 3D positions
+  //   F  #F by 3 eigne Matrix of face (triangle) indices
+  //   corner_threshold  threshold in degrees on sharp angles
+  // Output:
+  //   CN  #F*3 by 3 eigen Matrix of mesh vertex 3D normals, where the normal
+  //     for corner F(i,j) is at CN(i*3+j,:) 
+  inline void per_corner_normals(
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    const double corner_threshold,
+    Eigen::MatrixXd & CN);
+  // Other Inputs:
+  //   FN  #F by 3 eigen Matrix of face normals
+  //   VF  map from vertices to list of incident faces
+  inline void per_corner_normals(
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    const Eigen::MatrixXd & FN,
+    const std::vector<std::vector<int> >& VF,
+    const double corner_threshold,
+    Eigen::MatrixXd & CN);
+}
+
+// Implementation
+#include "vf.h"
+#include "per_face_normals.h"
+#include "PI.h"
+
+inline void igl::per_corner_normals(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const double corner_threshold,
+  Eigen::MatrixXd & CN)
+{
+  using namespace igl;
+  using namespace Eigen;
+  using namespace std;
+  MatrixXd FN;
+  per_face_normals(V,F,FN);
+  vector<vector<int> > VF,VFi;
+  vf(V,F,VF,VFi);
+  return per_corner_normals(V,F,FN,VF,corner_threshold,CN);
+}
+
+inline void igl::per_corner_normals(
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    const Eigen::MatrixXd & FN,
+    const std::vector<std::vector<int> >& VF,
+    const double corner_threshold,
+    Eigen::MatrixXd & CN)
+{
+  using namespace igl;
+  using namespace Eigen;
+  using namespace std;
+
+  // number of faces
+  const int m = F.rows();
+  // initialize output to zero
+  CN = MatrixXd::Constant(m*3,3,0);
+
+  // loop over faces
+  for(size_t i = 0;i<m;i++)
+  {
+    // Normal of this face
+    Vector3d fn = FN.row(i);
+    // loop over corners
+    for(size_t j = 0;j<3;j++)
+    {
+      std::vector<int> incident_faces = VF[F(i,j)];
+      // loop over faces sharing vertex of this corner
+      for(int k = 0;k<(int)incident_faces.size();k++)
+      {
+        Vector3d ifn = FN.row(incident_faces[k]);
+        // dot product between face's normal and other face's normal
+        double dp = fn.dot(ifn);
+        // if difference in normal is slight then add to average
+        if(dp > cos(corner_threshold*PI/180))
+        {
+          // add to running sum
+          CN.row(i*3+j) += ifn;
+        // else ignore
+        }else
+        {
+        }
+      }
+      // normalize to take average
+      double length = CN.row(i*3+j).norm();
+      CN.row(i*3+j) /= length;
+    }
+  }
+}
+

+ 85 - 0
texture_from_tga.h

@@ -0,0 +1,85 @@
+#ifndef IGL_TEXTURE_FROM_TGA
+#define IGL_TEXTURE_FROM_TGA
+
+#if __APPLE__
+#  include <OpenGL/gl.h>
+#else
+#  ifdef _WIN32
+#    define NOMINMAX
+#    include <Windows.h>
+#    undef NOMINMAX
+#  endif
+#  include <GL/gl.h>
+#endif
+
+namespace igl
+{
+  // Read an image from a .tga file and use it as a texture
+  //
+  // Input:
+  //  tga_file  path to .tga file
+  // Output:
+  //  id  of generated openGL texture
+  // Returns true on success, false on failure
+  bool texture_from_tga(const std::string tga_file, GLuint & id);
+}
+
+
+// Implementation
+#include "tga.h"
+
+bool igl::texture_from_tga(const std::string tga_file, GLuint & id)
+{
+  using namespace std;
+  using namespace igl;
+
+  // read pixels to tga file
+  FILE * imgFile;
+  // "-" as input file name is code for read from stdin
+  imgFile = fopen(tga_file.c_str(),"r");
+  if(NULL==imgFile)
+  {
+    printf("IOError: %s could not be opened...",tga_file.c_str());
+    return false;
+  }
+
+  // gliReadTGA annoyingly uses char * instead of const char *
+  size_t len = tga_file.length();
+  char* tga_file_char = new char [ len + 1 ];
+  strcpy( tga_file_char, tga_file.c_str() );
+  // read image
+  gliGenericImage* img = gliReadTGA(imgFile, tga_file_char, 0, 0);
+  // clean up filename buffer
+  delete[] tga_file_char;
+  fclose( imgFile );
+
+  // set up texture mapping parameters and generate texture id
+  glGenTextures(1,&id);
+  glBindTexture(GL_TEXTURE_2D, id);
+  // Texture parameters
+  float empty[] = {1.0f,1.0f,1.0f,0.0f};
+  glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_BORDER_COLOR,empty);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+  //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+  //  GL_LINEAR_MIPMAP_NEAREST);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+    GL_LINEAR);
+
+  // OpenGL by default tries to read data in multiples of 4, if our data is
+  // only RGB or BGR and the width is not divible by 4 then we need to alert
+  // opengl
+  if((img->width % 4) != 0 && 
+   (img->format == GL_RGB || 
+    img->format == GL_BGR))
+  {
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+  }
+
+  // Load texture
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img->width,
+    img->height, 0, img->format, GL_UNSIGNED_BYTE,
+    img->pixels);
+  return id;
+}
+#endif

+ 648 - 0
tga.h

@@ -0,0 +1,648 @@
+#pragma once
+
+// interface for TrueVision (TGA) image file loader
+//
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// WARNING
+//
+// THIS DOES NOT DEAL WITH VERTICALLY FLIPPED DATA CORRECTLY
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/* This file is derived from (actually an earlier version of)... */
+
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * $Id: tga.cpp,v 1.1.2.5 2007-05-10 02:10:07 elif Exp $
+ * TrueVision Targa loading and saving file filter for the Gimp.
+ * Targa code Copyright (C) 1997 Raphael FRANCOIS and Gordon Matzigkeit
+ *
+ * The Targa reading and writing code was written from scratch by
+ * Raphael FRANCOIS <fraph@ibm.net> and Gordon Matzigkeit
+ * <gord@gnu.ai.mit.edu> based on the TrueVision TGA File Format
+ * Specification, Version 2.0:
+ *
+ *   <URL:ftp://ftp.truevision.com/pub/TGA.File.Format.Spec/>
+ *
+ * It does not contain any code written for other TGA file loaders.
+ * Not even the RLE handling. ;)
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <iostream>
+
+#if defined(_WIN32) || defined(_WIN64)
+#include <windows.h>
+#endif
+
+#if defined(__APPLE__) || defined(__MACH__)
+#include <OpenGL/gl.h>
+#include <GLUT/glut.h>
+#else
+#include <GL/gl.h>
+#include <GL/glut.h>
+#endif
+
+
+// wrap everything in a namespace and expose read_tga function and Image type only
+
+namespace igl{
+
+////////////////////////////////////////////////////////////////////
+// declaration
+
+typedef struct {
+
+  GLsizei  width;
+  GLsizei  height;
+  GLint    components;
+  GLenum   format;
+
+  GLsizei  cmapEntries;
+  GLenum   cmapFormat;
+  GLubyte *cmap;
+
+  GLubyte *pixels;
+  
+} gliGenericImage;
+
+typedef struct {
+  unsigned char idLength;
+  unsigned char colorMapType;
+
+  /* The image type. */
+#define TGA_TYPE_MAPPED 1
+#define TGA_TYPE_COLOR 2
+#define TGA_TYPE_GRAY 3
+#define TGA_TYPE_MAPPED_RLE 9
+#define TGA_TYPE_COLOR_RLE 10
+#define TGA_TYPE_GRAY_RLE 11
+  unsigned char imageType;
+
+  /* Color Map Specification. */
+  /* We need to separately specify high and low bytes to avoid endianness
+     and alignment problems. */
+  unsigned char colorMapIndexLo, colorMapIndexHi;
+  unsigned char colorMapLengthLo, colorMapLengthHi;
+  unsigned char colorMapSize;
+
+  /* Image Specification. */
+  unsigned char xOriginLo, xOriginHi;
+  unsigned char yOriginLo, yOriginHi;
+
+  unsigned char widthLo, widthHi;
+  unsigned char heightLo, heightHi;
+
+  unsigned char bpp;
+
+  /* Image descriptor.
+     3-0: attribute bpp
+     4:   left-to-right ordering
+     5:   top-to-bottom ordering
+     7-6: zero
+     */
+#define TGA_DESC_ABITS 0x0f
+#define TGA_DESC_HORIZONTAL 0x10
+#define TGA_DESC_VERTICAL 0x20
+  unsigned char descriptor;
+
+} TgaHeader;
+
+typedef struct {
+  unsigned int extensionAreaOffset;
+  unsigned int developerDirectoryOffset;
+#define TGA_SIGNATURE "TRUEVISION-XFILE"
+  char signature[16];
+  char dot;
+  char null;
+} TgaFooter;
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// implementation
+
+
+static char error[256];
+static unsigned int _verbose = 0;
+static int totbytes = 0;
+
+typedef struct {
+  unsigned char *statebuf;
+  int statelen;
+  int laststate;
+} RLEstate;
+
+static int
+std_fread(RLEstate *rleInfo, unsigned char *buf, size_t datasize, size_t nelems, FILE *fp)
+{
+  if (_verbose > 1) {
+    totbytes += nelems * datasize;
+    printf("TGA: std_fread %d (total %d)\n",
+      (int)(nelems * datasize), totbytes);
+  }
+  return fread(buf, datasize, nelems, fp);
+}
+
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+#define RLE_PACKETSIZE 0x80
+
+/* Decode a bufferful of file. */
+static int
+rle_fread(RLEstate *rleInfo, unsigned char *vbuf, size_t datasize, size_t nelems, FILE *fp)
+{
+
+  unsigned char *buf = vbuf;
+  int j, k;
+  int buflen, count, bytes, curbytes;
+  unsigned char *p;
+
+  /* Scale the buffer length. */
+  buflen = nelems * datasize;
+
+  j = 0;
+  curbytes = totbytes;
+  while (j < buflen) {
+    if (rleInfo->laststate < rleInfo->statelen) {
+      /* Copy bytes from our previously decoded buffer. */
+      bytes = MIN(buflen - j, rleInfo->statelen - rleInfo->laststate);
+      memcpy(buf + j, rleInfo->statebuf + rleInfo->laststate, bytes);
+      j += bytes;
+      rleInfo->laststate += bytes;
+
+      /* If we used up all of our state bytes, then reset them. */
+      if (rleInfo->laststate >= rleInfo->statelen) {
+        rleInfo->laststate = 0;
+        rleInfo->statelen = 0;
+      }
+
+      /* If we filled the buffer, then exit the loop. */
+      if (j >= buflen) break;
+    }
+
+    /* Decode the next packet. */
+    count = fgetc(fp);
+    if (count == EOF) {
+      if (_verbose) printf("TGA: hit EOF while looking for count\n");
+      return j / datasize;
+    }
+
+    /* Scale the byte length to the size of the data. */
+    bytes = ((count & ~RLE_PACKETSIZE) + 1) * datasize;
+
+    if (j + bytes <= buflen) {
+      /* We can copy directly into the image buffer. */
+      p = buf + j;
+    } else {
+#ifdef PROFILE
+      printf("TGA: needed to use statebuf for %d bytes\n", buflen - j);
+#endif
+      /* Allocate the state buffer if we haven't already. */
+      if (!rleInfo->statebuf) {
+        rleInfo->statebuf = (unsigned char *) malloc(RLE_PACKETSIZE * datasize);
+      }
+      p = rleInfo->statebuf;
+    }
+
+    if (count & RLE_PACKETSIZE) {
+      /* Fill the buffer with the next value. */
+      if (fread(p, datasize, 1, fp) != 1) {
+        if (_verbose) {
+          printf("TGA: EOF while reading %d/%d element RLE packet\n",
+            bytes, (int)datasize);
+        }
+        return j / datasize;
+      }
+
+      /* Optimized case for single-byte encoded data. */
+      if (datasize == 1) {
+        memset(p + 1, *p, bytes - 1);
+      } else {
+        for (k = datasize; k < bytes; k += datasize) {
+          memcpy(p + k, p, datasize);
+        }
+      }
+    } else {
+      /* Read in the buffer. */
+      if (fread(p, bytes, 1, fp) != 1) {
+        if (_verbose) {
+          printf("TGA: EOF while reading %d/%d element raw packet\n",
+            bytes, (int)datasize);
+        }
+        return j / datasize;
+      }
+    }
+
+    if (_verbose > 1) {
+      totbytes += bytes;
+      if (_verbose > 2) {
+        printf("TGA: %s packet %d/%d\n",
+          (count & RLE_PACKETSIZE) ? "RLE" : "raw",
+          bytes, totbytes);
+      }
+    }
+
+    /* We may need to copy bytes from the state buffer. */
+    if (p == rleInfo->statebuf) {
+      rleInfo->statelen = bytes;
+    } else {
+      j += bytes;
+    }
+  }
+
+  if (_verbose > 1) {
+    printf("TGA: rle_fread %d/%d (total %d)\n",
+    (int) ( nelems * datasize), totbytes - curbytes, totbytes);
+  }
+  return nelems;
+}
+
+static gliGenericImage *
+gliReadTGA(FILE *fp, const char *name, int hflip, int vflip)
+{
+  TgaHeader tgaHeader;
+  TgaFooter tgaFooter;
+  char horzrev, vertrev;
+  int width, height, bpp;
+  int start, end, dir;
+  int i, j, k;
+  int pelbytes, wbytes;
+  GLenum format;
+  int components;
+  RLEstate rleRec;
+  RLEstate *rleInfo;
+  int rle;
+  int index, colors, length;
+  GLubyte *cmap, *pixels, *data;
+  int (*myfread)(RLEstate *rleInfo, unsigned char*, size_t, size_t, FILE*);
+  gliGenericImage *genericImage;
+
+  /* Check the footer. */
+  if (fseek(fp, 0L - sizeof(tgaFooter), SEEK_END)
+      || fread(&tgaFooter, sizeof(tgaFooter), 1, fp) != 1) {
+    sprintf(error, "TGA: Cannot read footer from \"%s\"", name);
+    if (_verbose) printf("%s\n", error);
+    return NULL;
+  }  
+
+  /* Check the signature. */
+  if (memcmp(tgaFooter.signature, TGA_SIGNATURE,
+             sizeof(tgaFooter.signature)) == 0) {
+    if (_verbose) printf("TGA: found New TGA\n");
+  } else {
+    if (_verbose) printf("TGA: found Original TGA\n");
+  }
+
+  if (fseek(fp, 0, SEEK_SET) ||
+      fread(&tgaHeader, sizeof(tgaHeader), 1, fp) != 1) {
+    sprintf(error, "TGA: Cannot read header from \"%s\"", name);
+    if (_verbose) printf("%s\n", error);
+    return NULL;
+  }
+
+  if (_verbose && tgaHeader.idLength) {
+    char *idString = (char*) malloc(tgaHeader.idLength);
+    
+    if (fread(idString, tgaHeader.idLength, 1, fp) != 1) {
+      sprintf(error, "TGA: Cannot read ID field in \"%s\"", name);
+      printf("%s\n", error);
+    } else {
+      printf("TGA: ID field: \"%*s\"\n", tgaHeader.idLength, idString);
+    }
+    free(idString);
+  } else {
+    /* Skip the image ID field. */
+    if (tgaHeader.idLength && fseek(fp, tgaHeader.idLength, SEEK_CUR)) {
+      sprintf(error, "TGA: Cannot skip ID field in \"%s\"", name);
+      if (_verbose) printf("%s\n", error);
+      return NULL;
+    }
+  }
+  
+  /* Reassemble the multi-byte values correctly, regardless of
+     host endianness. */
+  width = (tgaHeader.widthHi << 8) | tgaHeader.widthLo;
+  height = (tgaHeader.heightHi << 8) | tgaHeader.heightLo;
+  bpp = tgaHeader.bpp;
+  if (_verbose) {
+    printf("TGA: width=%d, height=%d, bpp=%d\n", width, height, bpp);
+  }
+
+  horzrev = tgaHeader.descriptor & TGA_DESC_HORIZONTAL;
+  vertrev = tgaHeader.descriptor & TGA_DESC_VERTICAL;
+  //vertrev=0;
+
+//   // JASON - we can force this stuff if we want
+//   if( hflip )
+//       horzrev = 1;
+  if( vflip )
+      vertrev = 1;
+
+  if (_verbose && horzrev) printf("TGA: horizontal reversed\n");
+  if (_verbose && vertrev) printf("TGA: vertical reversed\n");
+
+  rle = 0;
+  switch (tgaHeader.imageType) {
+  case TGA_TYPE_MAPPED_RLE:
+    rle = 1;
+    if (_verbose) printf("TGA: run-length encoded\n");
+  case TGA_TYPE_MAPPED:
+    /* Test for alpha channel. */
+    format = GL_COLOR_INDEX;
+    components = 1;
+    if (_verbose) {
+      printf("TGA: %d bit indexed image (%d bit palette)\n",
+        tgaHeader.colorMapSize, bpp);
+    }
+    break;
+
+  case TGA_TYPE_GRAY_RLE:
+    rle = 1;
+    if (_verbose) printf("TGA: run-length encoded\n");
+  case TGA_TYPE_GRAY:
+    format = GL_LUMINANCE;
+    components = 1;
+    if (_verbose) printf("TGA: %d bit grayscale image\n", bpp);
+    break;
+
+  case TGA_TYPE_COLOR_RLE:
+    rle = 1;
+    if (_verbose) printf("TGA: run-length encoded\n");
+  case TGA_TYPE_COLOR:
+    /* Test for alpha channel. */
+    if (bpp == 32) {
+      format = GL_BGRA_EXT;
+      components = 4;
+      if (_verbose) {
+        printf("TGA: %d bit color image with alpha channel\n", bpp);
+      }
+    } else {
+      format = GL_BGR_EXT;
+      components = 3;
+      if (_verbose) printf("TGA: %d bit color image\n", bpp);
+    }
+    break;
+
+  default:
+    sprintf(error,
+      "TGA: unrecognized image type %d\n", tgaHeader.imageType);
+    if (_verbose) printf("%s\n", error);
+    return NULL;
+  }
+
+  if ((format == GL_BGRA_EXT && bpp != 32) ||
+      (format == GL_BGR_EXT && bpp != 24) ||
+      ((format == GL_LUMINANCE || format == GL_COLOR_INDEX) && bpp != 8)) {
+    /* FIXME: We haven't implemented bit-packed fields yet. */
+    fprintf(stderr, "bpp %d, format %x\n", bpp, (unsigned int)format); 
+    sprintf(error, "TGA: channel sizes other than 8 bits are unimplemented");
+    if (_verbose) printf("%s\n", error);
+    return NULL;
+  }
+
+  /* Check that we have a color map only when we need it. */
+  if (format == GL_COLOR_INDEX) {
+    if (tgaHeader.colorMapType != 1) {
+      sprintf(error, "TGA: indexed image has invalid color map type %d\n",
+        tgaHeader.colorMapType);
+      if (_verbose) printf("%s\n", error);
+      return NULL;
+    }
+  } else if (tgaHeader.colorMapType != 0) {
+    sprintf(error, "TGA: non-indexed image has invalid color map type %d\n",
+      tgaHeader.colorMapType);
+    if (_verbose) printf("%s\n", error);
+    return NULL;
+  }
+
+  if (tgaHeader.colorMapType == 1) {
+    /* We need to read in the colormap. */
+    index = (tgaHeader.colorMapIndexHi << 8) | tgaHeader.colorMapIndexLo;
+    length = (tgaHeader.colorMapLengthHi << 8) | tgaHeader.colorMapLengthLo;
+
+    if (_verbose) {
+      printf("TGA: reading color map (%d + %d) * (%d / 8)\n",
+        index, length, tgaHeader.colorMapSize);
+    }
+    if (length == 0) {
+      sprintf(error, "TGA: invalid color map length %d", length);
+      if (_verbose) printf("%s\n", error);
+      return NULL;
+    }
+    if (tgaHeader.colorMapSize != 24) {
+      /* We haven't implemented bit-packed fields yet. */
+      sprintf(error, "TGA: channel sizes other than 8 bits are unimplemented");
+      if (_verbose) printf("%s\n", error);
+      return NULL;
+    }
+
+    pelbytes = tgaHeader.colorMapSize / 8;
+    colors = length + index;
+    cmap = (GLubyte*)malloc (colors * pelbytes);
+
+    /* Zero the entries up to the beginning of the map. */
+    memset(cmap, 0, index * pelbytes);
+
+    /* Read in the rest of the colormap. */
+    if (fread(cmap, pelbytes, length, fp) != (size_t) length) {
+      sprintf(error, "TGA: error reading colormap (ftell == %ld)\n",
+        ftell (fp));
+      if (_verbose) printf("%s\n", error);
+      return NULL;
+    }
+
+    if (pelbytes >= 3) {
+      /* Rearrange the colors from BGR to RGB. */
+      int tmp;
+      for (j = index; j < length * pelbytes; j += pelbytes) {
+        tmp = cmap[j];
+        cmap[j] = cmap[j + 2];
+        cmap[j + 2] = tmp;
+      }
+    }
+  } else {
+    colors = 0;
+    cmap = NULL;
+  }
+
+  /* Allocate the data. */
+  pelbytes = bpp / 8;
+  pixels = (unsigned char *) malloc (width * height * pelbytes);
+
+  if (rle) {
+    rleRec.statebuf = 0;
+    rleRec.statelen = 0;
+    rleRec.laststate = 0;
+    rleInfo = &rleRec;
+    myfread = rle_fread;
+  } else {
+    rleInfo = NULL;
+    myfread = std_fread;
+  }
+
+  wbytes = width * pelbytes;
+
+  if (vertrev) {
+    start = 0;
+    end = height;
+    dir = 1;
+  } else {
+    /* We need to reverse loading order of rows. */
+    start = height-1;
+    end = -1;
+    dir = -1;
+  }
+
+  for (i = start; i != end; i += dir) {
+    data = pixels + i*wbytes;
+
+    /* Suck in the data one row at a time. */
+    if (myfread(rleInfo, data, pelbytes, width, fp) != width) {
+      /* Probably premature end of file. */
+      if (_verbose) {
+        printf ("TGA: error reading (ftell == %ld, width=%d)\n",
+          ftell(fp), width);
+      }
+      return NULL;
+    }  
+
+    if (horzrev) {
+      /* We need to mirror row horizontally. */
+      for (j = 0; j < width/2; j++) {
+        GLubyte tmp;
+
+        for (k = 0; k < pelbytes; k++) {
+          tmp = data[j*pelbytes+k];
+          data[j*pelbytes+k] = data[(width-j-1)*pelbytes+k];
+          data[(width-j-1)*pelbytes+k] = tmp;
+        }
+      }
+    }
+  }
+
+  if (rle) {
+    free(rleInfo->statebuf);
+  }
+
+  if (fgetc (fp) != EOF) {
+    if (_verbose) printf ("TGA: too much input data, ignoring extra...\n");
+  }
+
+  genericImage = (gliGenericImage*) malloc(sizeof(gliGenericImage));
+  genericImage->width = width;
+  genericImage->height = height;
+  genericImage->format = format;
+  genericImage->components = components;
+  genericImage->cmapEntries = colors;
+  genericImage->cmapFormat = GL_BGR_EXT;  // XXX fix me
+  genericImage->cmap = cmap;
+  genericImage->pixels = pixels;
+
+  return genericImage;
+}
+
+static int
+gli_verbose(int new_verbose)
+{
+  _verbose = new_verbose;
+  return _verbose;
+}
+
+
+
+// added 10/2005, Denis Zorin
+// a very simple TGA output, supporting 
+// uncompressed luminance RGB and RGBA 
+// G22.2270 students: this is C (no C++) 
+// so this is not the style I would encourage
+// you to use; I used it for consistency 
+// with the rest of the code in this file 
+
+
+// fixed header values for the subset of TGA we use for writing
+static unsigned char TGAHeaderColor[12] = 
+  { 0,// 0 ID length = no id
+    0,// 1 color map type = no color map
+    2,// 2 image type = uncompressed true color
+    0, 0, 0, 0, 0,// color map spec = empty
+    0, 0,  // x origin of image 
+    0, 0   // y origin of image
+  };
+
+static unsigned char TGAHeaderBW[12] = 
+  { 0,// 0 ID length = no id
+    0,// 1 color map type = no color map
+    3,// 3 image type = uncompressed black and white
+    0, 0, 0, 0, 0,// color map spec = empty
+    0, 0,  // x origin of image 
+    0, 0   // y origin of image
+  };
+
+// this makes sure that 
+// image size is written in correct format 
+// and byte order (least first)
+static void write16bit(int n, FILE* fp) { 
+  unsigned char bytes[] = { n % 256, n / 256 };
+  fwrite(bytes, 2, sizeof(unsigned char),fp);
+}
+
+
+
+static void writeTGA( gliGenericImage* image, FILE *fp) {
+
+  assert(!image->cmap); // we do not deal with color map images
+    
+  if(image->components == 3 || image->components == 4) 
+    fwrite(TGAHeaderColor, 12, sizeof(unsigned char),fp);
+  else { 
+    if(image->components == 1 ) 
+      fwrite(TGAHeaderBW, 12, sizeof(unsigned char),fp);        
+    else { fprintf(stderr,"Supported component number: 1,3 or 4\n"); exit(1); }
+  }
+
+  write16bit(image->width,fp);  
+  write16bit(image->height,fp);  
+  switch (image->components ) { 
+  case 1: 
+    putc(8,fp);
+    break;
+  case 3: 
+    putc(24,fp); 
+    break;
+  case 4:
+    putc(32,fp);
+    break;
+  default: fprintf(stderr,"Supported component number: 1,3 or 4\n"); exit(1); 
+  };
+  
+  if(image-> components == 4) 
+    putc(0x04,fp); // bottom left image (0x00) + 8 bit alpha (0x4)
+  else 
+    putc(0x00,fp);
+
+  fwrite(image->pixels, image->height*image->width*image->components, sizeof(char),fp);
+}
+
+} // end of namespace

+ 5 - 5
writeMESH.h

@@ -76,10 +76,10 @@ inline bool igl::writeMESH(
   // print tet vertices
   fprintf(mesh_file,"Vertices\n");
   // print number of tet vertices
-  size_t number_of_tet_vertices = V.rows();
+  int number_of_tet_vertices = V.rows();
   fprintf(mesh_file,"%ld\n",number_of_tet_vertices);
   // loop over tet vertices
-  for(size_t i = 0;i<number_of_tet_vertices;i++)
+  for(int i = 0;i<number_of_tet_vertices;i++)
   {
     // print position of ith tet vertex
     fprintf(mesh_file,"%lg %lg %lg 1\n",
@@ -92,7 +92,7 @@ inline bool igl::writeMESH(
   // print faces
   fprintf(mesh_file,"Triangles\n");
   // print number of triangles
-  size_t number_of_triangles = F.rows();
+  int number_of_triangles = F.rows();
   fprintf(mesh_file,"%ld\n",number_of_triangles);
   // loop over faces
   for(int i = 0;i<number_of_triangles;i++)
@@ -105,11 +105,11 @@ inline bool igl::writeMESH(
   }
   // print tetrahedra
   fprintf(mesh_file,"Tetrahedra\n");
-  size_t number_of_tetrahedra = T.rows();
+  int number_of_tetrahedra = T.rows();
   // print number of tetrahedra
   fprintf(mesh_file,"%ld\n",number_of_tetrahedra);
   // loop over tetrahedra
-  for(size_t i = 0; i < number_of_tetrahedra;i++)
+  for(int i = 0; i < number_of_tetrahedra;i++)
   {
     // mesh standard uses 1-based indexing
     fprintf(mesh_file, "%d %d %d %d 1\n",