Beispiel #1
0
int R3Mesh::
ReadImage(const char *filename)
{
  // Create a mesh by reading an image file, 
  // constructing vertices at (x,y,luminance), 
  // and connecting adjacent pixels into faces. 
  // That is, the image is interpretted as a height field, 
  // where the luminance of each pixel provides its z-coordinate.

  // Read image
  R2Image *image = new R2Image();
  if (!image->Read(filename)) return 0;

  // Create vertices and store in arrays
  R3MeshVertex ***vertices = new R3MeshVertex **[image->Width() ];
  for (int i = 0; i < image->Width(); i++) {
    vertices[i] = new R3MeshVertex *[image->Height() ];
    for (int j = 0; j < image->Height(); j++) {
      double luminance = image->Pixel(i, j).Luminance();
      double z = luminance * image->Width();
      R3Point position((double) i, (double) j, z);
      R2Point texcoords((double) i, (double) j);
      vertices[i][j] = CreateVertex(position, R3zero_vector, texcoords);
    }
  }

  // Create faces
  vector<R3MeshVertex *> face_vertices;
  for (int i = 1; i < image->Width(); i++) {
    for (int j = 1; j < image->Height(); j++) {
      face_vertices.clear();
      face_vertices.push_back(vertices[i-1][j-1]);
      face_vertices.push_back(vertices[i][j-1]);
      face_vertices.push_back(vertices[i][j]);
      CreateFace(face_vertices);
      face_vertices.clear();
      face_vertices.push_back(vertices[i-1][j-1]);
      face_vertices.push_back(vertices[i][j]);
      face_vertices.push_back(vertices[i-1][j]);
      CreateFace(face_vertices);
    }
  }

  // Delete vertex arrays
  for (int i = 0; i < image->Width(); i++) delete [] vertices[i];
  delete [] vertices;

  // Delete image
  delete image;

  // Return success
  return 1;
}
static R2Image *
ReadImage(const char *filename)
{
    // Allocate a image
    R2Image *image = new R2Image();
    if (!image) {
        fprintf(stderr, "Unable to allocate image");
        return NULL;
    }
    
    // Read image
    if (!image->Read(filename)) {
        fprintf(stderr, "Unable to read image file %s", filename);
        return NULL;
    }
    
    // Print message
    if (print_verbose) {
        printf("Read image from %s\n", filename);
        printf("  Resolution = %d %d\n", image->Width(), image->Height());
        printf("  L1Norm = %g\n", image->L1Norm());
        printf("  L2Norm = %g\n", image->L2Norm());
        fflush(stdout);
    }
    
    // Return image
    return image;
}
void R2Image::
Multiply(const R2Image& image) 
{
  // Multiply by image pixel-by-pixel
  assert(image.Width() == Width());
  assert(image.Height() == Height());
  assert(image.NChannels() == NChannels());
  int nvalues = NValues();
  for (int i = 0; i < nvalues; i++) {
    pixels[i] *= image.pixels[i];
  }
}
void R2Image::
Subtract(const R2Image& image) 
{
  // Subtract image pixel-by-pixel
  assert(image.Width() == Width());
  assert(image.Height() == Height());
  assert(image.NChannels() == NChannels());
  int nvalues = NValues();
  for (int i = 0; i < nvalues; i++) {
    pixels[i] -= image.pixels[i];
  }
}
void R2Image::
Filter(const R2Image& filter) 
{
  // Get useful variables
  int xr = filter.Width()/2;
  int yr = filter.Height()/2;
  R2Image copy(*this);

  // This is the straight-forward implementation (slow for large filters)
  for (int j = 0; j < Height(); j++) {
    for (int i = 0; i < Width(); i++) {
      for (int c = 0; c < NChannels(); c++) {
        int fc = (NChannels() == filter.NChannels()) ? c : 0;

        // Compute new value 
        double sum = 0;
        for (int s = 0; s < filter.Width(); s++) {
          int x = i - xr + s;
          if (x < 0) x = 0;
          else if (x >= Width()) x = Width()-1;
          for (int t = 0; t < filter.Height(); t++) {
            int y = j - yr + t;
            if (y < 0) y = 0;
            else if (y >= Height()) y = Height()-1;
            double filter_value = filter.Value(s, t, fc);
            double image_value = copy.Value(x, y, c);
            sum += filter_value * image_value;
          }
        }

        // Assign new value for channel
        SetValue(i, j, c, sum);
      }
    }
  }
}
void R2Image::
Divide(const R2Image& image) 
{
  // Add image pixel-by-pixel
  assert(image.Width() == Width());
  assert(image.Height() == Height());
  assert(image.NChannels() == NChannels());
  int nvalues = NValues();
  for (int i = 0; i < nvalues; i++) {
    if (image.pixels[i] == 0) {
      if (pixels[i] == 0.0) continue;
      else pixels[i] = FLT_MAX;
    }
    else {
      pixels[i] /= image.pixels[i];
    }
  }
}
void LoadMaterial(R3Material *material) 
{
  GLfloat c[4];

  // Check if same as current
  static R3Material *current_material = NULL;
  if (material == current_material) return;
  current_material = material;

  // Compute "opacity"
  double opacity = 1 - material->kt.Luminance();

  // Load ambient
  c[0] = material->ka[0];
  c[1] = material->ka[1];
  c[2] = material->ka[2];
  c[3] = opacity;
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, c);

  // Load diffuse
  c[0] = material->kd[0];
  c[1] = material->kd[1];
  c[2] = material->kd[2];
  c[3] = opacity;
  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, c);

  // Load specular
  c[0] = material->ks[0];
  c[1] = material->ks[1];
  c[2] = material->ks[2];
  c[3] = opacity;
  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c);

  // Load emission
  c[0] = material->emission.Red();
  c[1] = material->emission.Green();
  c[2] = material->emission.Blue();
  c[3] = opacity;
  glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, c);

  // Load shininess
  c[0] = material->shininess;
  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, c[0]);

  // Load texture
  if (material->texture) {
    if (material->texture_index <= 0) {
      // Create texture in OpenGL
      GLuint texture_index;
      glGenTextures(1, &texture_index);
      material->texture_index = (int) texture_index;
      glBindTexture(GL_TEXTURE_2D, material->texture_index); 
      R2Image *image = material->texture;
      int npixels = image->NPixels();
      R2Pixel *pixels = image->Pixels();
      GLfloat *buffer = new GLfloat [ 4 * npixels ];
      R2Pixel *pixelsp = pixels;
      GLfloat *bufferp = buffer;
      for (int j = 0; j < npixels; j++) { 
        *(bufferp++) = pixelsp->Red();
        *(bufferp++) = pixelsp->Green();
        *(bufferp++) = pixelsp->Blue();
        *(bufferp++) = pixelsp->Alpha();
        pixelsp++;
      }
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
      glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
      glTexImage2D(GL_TEXTURE_2D, 0, 4, image->Width(), image->Height(), 0, GL_RGBA, GL_FLOAT, buffer);
      delete [] buffer;
    }

    // Select texture
    glBindTexture(GL_TEXTURE_2D, material->texture_index); 
    glEnable(GL_TEXTURE_2D);
  }
  else {
    glDisable(GL_TEXTURE_2D);
  }

  // Enable blending for transparent surfaces
  if (opacity < 1) {
    glDepthMask(false);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);
  }
  else {
    glDisable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ZERO);
    glDepthMask(true);
  }
}