<commit_before>// -----------------------------------------------------------------------------
// Copyright  : (C) 2014 Andreas-C. Bernstein
// License    : MIT (see the file LICENSE)
// Maintainer : Andreas-C. Bernstein <andreas.bernstein@uni-weimar.de>
// Stability  : experimental
//
// Renderer
// -----------------------------------------------------------------------------

#include "renderer.hpp"
#include "optional_hit.hpp"
#include "ray.hpp"
#include "scene.hpp"
#include "camera.hpp"
#include "sdf_loader.hpp"
#include "color.hpp"
#include "shape.hpp"
#include <algorithm> // min_element
#include <glm/glm.hpp>
#include <glm/vec3.hpp>

Renderer::Renderer(unsigned w, unsigned h, std::string const& file):
	width_(w),
	height_(h),
	colorbuffer_(w*h, Color(0.0, 0.0, 0.0)),
	filename_(file),
	ppm_(width_, height_)
	{}

Renderer::Renderer():
	width_(0),
	height_(0),
	colorbuffer_(0, Color(0.0, 0.0, 0.0)),
	filename_(""),
	ppm_(width_, height_)
	{}

unsigned Renderer::get_width() const{
  return width_;
}
unsigned Renderer::get_height() const{
  return height_;
}
std::string Renderer::get_filename() const{
  return filename_;
}
Scene Renderer::get_scene() const{
  return scene_;
}

Renderer& Renderer::operator= (Renderer const& rhs){
  width_ = rhs.get_width();
  height_ = rhs.get_height();
  filename_ = rhs.get_filename();
  return *this;
}

void Renderer::render()
{
  const std::size_t checkersize = 20;

  for (unsigned y = 0; y < height_; ++y) {
    for (unsigned x = 0; x < width_; ++x) {
      Pixel p(x,y);
      if ( ((x/checkersize)%2) != ((y/checkersize)%2)) {
        p.color = Color(0.0, 1.0, float(x)/height_);
      } else {
        p.color = Color(1.0, 0.0, float(y)/width_);
      }

      write(p);
    }
  }
  ppm_.save(filename_);
}

void Renderer::write(Pixel const& p)
{
  // flip pixels, because of opengl glDrawPixels
  size_t buf_pos = (width_*p.y + p.x);
  if (buf_pos >= colorbuffer_.size() || (int)buf_pos < 0) {
    std::cerr << "Fatal Error Renderer::write(Pixel p) : "
      << "pixel out of ppm_ : "
      << (int)p.x << "," << (int)p.y
      << std::endl;
  } else {
    colorbuffer_[buf_pos] = p.color;
  }

  ppm_.write(p);
}

Optional_hit Renderer::intersect(Ray const& ray) const{
  Optional_hit o;
  Optional_hit temp;
  std::vector<float> hits;

  for (std::vector<std::shared_ptr <Shape>>::const_iterator it = scene_.shapes.begin(); it != scene_.shapes.end(); ++it)
  {

    if (it == scene_.shapes.begin() || !o.hit)
    {
      o.hit = (*it)->intersect(ray, o.distance, o.intersection, o.normal);
      o.shape = &**it;
    }
    else
    {
      temp.hit = (*it)->intersect(ray, temp.distance, temp.intersection, temp.normal);
      temp.shape = &**it;
      if(o.distance > temp.distance && temp.distance > 0)
      {
        o = temp;
      }
    }

  }

  //std::cout << o.shape->get_name() << std::endl;

  return o;
}

Color Renderer::raytrace(Ray const& ray, int depth){
  Optional_hit o = intersect(ray);

  if(o.hit) return shade(ray, o, depth);
  else return scene_.ambient;
}

/*
Color Renderer::shade(Ray const& ray, Optional_hit const& o, int depth){ //braucht man noch color und recursion depth statt distance? wenn ja woher?

  Material temp_mat = scene_.material[o.shape->get_material()];

  float r = 0, g = 0, b = 0;
  float red = 0, green = 0, blue = 0;

  for(std::vector<Light_source>::const_iterator l = scene_.lights.begin(); l != scene_.lights.end(); ++l)
  {

    //Ray von Schnittpunkt zu Lichtquelle
    Ray lightray(o.intersection, glm::normalize((*l).get_position()));

    //Lichtintensität (Skalarprodukt, wird dann mit Reflexionskoeffizient und Helligkeit der Lichtquelle multipliziert)
    //oder Winkel zwischen Normale und Lichtquelle
    float tmp = glm::dot(o.normal, glm::normalize((*l).get_position()-o.intersection) );
    float angle_n_l = std::max(tmp, 0.0f);

    float temp_r = 0, temp_g = 0, temp_b = 0;

    Optional_hit shadow = intersect(lightray);
    if(!shadow.hit){

      /* Reflection ??
      //Winkel Kamera/Lichquelle
      float cam_light_angle = glm::dot(glm::normalize(o.intersection - scene_.cam.get_position()), glm::normalize((*l).get_position() - o.intersection));

      //Reflektionswinkel
      float reflection = cam_light_angle - (2* tmp);

      //Reflektionsvecktor
      glm::vec3 reflect_vec((2 * tmp * o.normal.x - (*l).get_position().x), (2 * tmp * o.normal.y - (*l).get_position().y), (2 * tmp * o.normal.z - (*l).get_position().z));

      //Ray reflection_ray(o.intersection, reflect_vec);
      //oder Ray reflection_ray = reflect_ray(o.intersection, o.normale, l.get_position()); ?

      Ray reflection_ray = reflect_ray(o.intersection, o.normal, (*l).get_position());

      temp_r = temp_mat.get_ks().r; //* pow(reflection, m);
      temp_g = temp_mat.get_ks().g; //* pow(reflection, m);
      temp_b = temp_mat.get_ks().b; //* pow(reflection, m);
      //......

      r += (*l).get_diffuse().r * (angle_n_l * temp_mat.get_kd().r + temp_mat.get_ks().r);
      g += (*l).get_diffuse().g * (angle_n_l * temp_mat.get_kd().g + temp_mat.get_ks().g);
      b += (*l).get_diffuse().b * (angle_n_l * temp_mat.get_kd().b + temp_mat.get_ks().b);

    }
    else{
      //Wenn im Schatten werden die Werde berechnet, sonst 0 ( Operator shadow.hit ? 1 : 0)
      r += temp_mat.get_kd().r * (*l).get_diffuse().r * angle_n_l;
      g += temp_mat.get_kd().g * (*l).get_diffuse().g * angle_n_l;
      b += temp_mat.get_kd().b * (*l).get_diffuse().b * angle_n_l;
    }

  }
  //mit Ambiente
  red = temp_mat.get_ka().r * scene_.ambient.r + r;
  green = temp_mat.get_ka().g * scene_.ambient.g + g;
  blue = temp_mat.get_ka().b * scene_.ambient.b + b;

  return Color(red, green, blue);

}*/

Color Renderer::shade(Ray const& ray, Optional_hit const& o, int depth){
  Color color; // Farbe des Strahls
  Ray rRay, tRay, sRay; // Reflexions-, Brechungs- und Schattenstrahlen
  Color rColor, tColor; // Farbe des reflektierten und gebrochenen Strahls
  Material temp_mat = scene_.material[o.shape->get_material()]; // Material des geschnittenen Shapes

  for (std::vector<Light_source>::const_iterator l = scene_.lights.begin(); l != scene_.lights.end(); ++l)
  {
    sRay = Ray(o.intersection, glm::normalize((*l).get_position()));
    //Teste ob Skalarprodukt von Normalen und sRay.direction positiv ist
    if(glm::dot(o.normal, sRay.direction) > 0){
      // Wieviel Licht wird von opaken und transparenten Flächen blockiert?
      Optional_hit shadow= intersect(sRay);
      float shading = glm::dot(o.normal, glm::normalize((*l).get_position()-o.intersection) );
      float shading_pos = std::max(shading, 0.0f);

      if (!shadow.hit)
      {
        color +=  (*l).get_diffuse() * (( temp_mat.get_kd() * shading_pos) + temp_mat.get_ks());
      }
      else{
        //Wenn im Schatten
        color +=  (*l).get_diffuse() * (( temp_mat.get_kd() * shading_pos));
      }

    }
  }

  if (depth <= 3)//3 = Max depth,
  {
    if (temp_mat.get_m() != 0)//Objekt reflektiert(spiegelt)
    {
      //Reflektionsray mit Reflektionsrichtung (ist der Einfallsvektor = Schnittpunkt?)
      rRay = reflect_ray(o.intersection, o.normal, o.intersection);
      rColor = raytrace(rRay, depth + 1);
      rColor *= temp_mat.get_m();
      //rColor *= temp_mat.get_ks();
      color += rColor;
    }
    /*
    if (temp_mat.get_opacity() != 0)//Objekt transparent(mit Refraktion)
    {
      //Ray in Brechungsrichtung
      tRay = Ray (o.intersection, (o.intersection + o.intersection * temp_mat.get_refract()));
      if(temp_mat.get_m() != 1)
        tColor = raytrace(tRay, depth + 1);
        tColor *= temp_mat.get_opacity();
        color += tColor;

    }*/
  }

  //ambiente Beleuchtung
  color += temp_mat.get_ka() * scene_.ambient;

  return color;
}

void Renderer::render_scene(std::string filename){

  //Scene wird geladen
  Sdf_loader loader{filename};
  scene_ = loader.load_scene(filename);

  //Daten aus Transferobjekt in den Renderer schreiben
  width_ = scene_.render.width;
  height_ = scene_.render.height;
  filename_= scene_.render.filename;
  std::vector<Color> buffer(width_*height_, Color(0.0, 0.0, 0.0));
  colorbuffer_=buffer;
  PpmWriter ppm(width_, height_);
  ppm_ = ppm;

  //Rays für das Bild gernerieren
  std::vector<Ray> rays;
  scene_.cam.generate_rays(width_, height_, rays);

  //Pixel für die Rays generieren
  std::vector<Pixel> pixel;
  for (unsigned i = 0; i < height_; ++i)
  {
    for (unsigned j = 0; j < width_; ++j)
    {
      Pixel p_temp(j,i);
      pixel.push_back(p_temp);
    }
  }

  std::vector<Pixel>::iterator j = pixel.begin();
  //Farbe für jeden Pixel berechnen
  for (std::vector<Ray>::iterator i = rays.begin(); i < rays.end(); ++i)
  {
    Color temp = raytrace(*i,1);
    (*j).color = temp;
    //std::cout << temp;
    write(*j);
    ++j;
  }
  ppm_.save(filename_);

}

Ray Renderer::reflect_ray(glm::vec3 const& intersection, glm::vec3 const& normale, glm::vec3 const& rayDirection) const{
	glm::vec3 spiegel{0.0f, 0.0f, 0.0f}; //neuer Ray direction kommt hier rein, origin ist intersection
	spiegel.x = (2*normale.x*normale.x*rayDirection.x + 2*normale.x*normale.y*rayDirection.y + 2*normale.x*normale.z*rayDirection.z - rayDirection.x);
	spiegel.y = (2*normale.x*normale.y*rayDirection.x + 2*normale.x*normale.y*rayDirection.y + 2*normale.y*normale.z*rayDirection.z - rayDirection.y);
	spiegel.z = (2*normale.y*normale.z*rayDirection.x + 2*normale.y*normale.z*rayDirection.y + 2*normale.z*normale.z*rayDirection.z - rayDirection.z);
	Ray newRay{intersection, spiegel}; //spiegel muss vielleicht *-1 genommen werden, bin mir nicht sicher ob der in die richtige Richtung zeigt
	return newRay;

}
<commit_msg>Update shade, transparenz<commit_after>// -----------------------------------------------------------------------------
// Copyright  : (C) 2014 Andreas-C. Bernstein
// License    : MIT (see the file LICENSE)
// Maintainer : Andreas-C. Bernstein <andreas.bernstein@uni-weimar.de>
// Stability  : experimental
//
// Renderer
// -----------------------------------------------------------------------------

#include "renderer.hpp"
#include "optional_hit.hpp"
#include "ray.hpp"
#include "scene.hpp"
#include "camera.hpp"
#include "sdf_loader.hpp"
#include "color.hpp"
#include "shape.hpp"
#include <algorithm> // min_element
#include <glm/glm.hpp>
#include <glm/vec3.hpp>

Renderer::Renderer(unsigned w, unsigned h, std::string const& file):
	width_(w),
	height_(h),
	colorbuffer_(w*h, Color(0.0, 0.0, 0.0)),
	filename_(file),
	ppm_(width_, height_)
	{}

Renderer::Renderer():
	width_(0),
	height_(0),
	colorbuffer_(0, Color(0.0, 0.0, 0.0)),
	filename_(""),
	ppm_(width_, height_)
	{}

unsigned Renderer::get_width() const{
  return width_;
}
unsigned Renderer::get_height() const{
  return height_;
}
std::string Renderer::get_filename() const{
  return filename_;
}
Scene Renderer::get_scene() const{
  return scene_;
}

Renderer& Renderer::operator= (Renderer const& rhs){
  width_ = rhs.get_width();
  height_ = rhs.get_height();
  filename_ = rhs.get_filename();
  return *this;
}

void Renderer::render()
{
  const std::size_t checkersize = 20;

  for (unsigned y = 0; y < height_; ++y) {
    for (unsigned x = 0; x < width_; ++x) {
      Pixel p(x,y);
      if ( ((x/checkersize)%2) != ((y/checkersize)%2)) {
        p.color = Color(0.0, 1.0, float(x)/height_);
      } else {
        p.color = Color(1.0, 0.0, float(y)/width_);
      }

      write(p);
    }
  }
  ppm_.save(filename_);
}

void Renderer::write(Pixel const& p)
{
  // flip pixels, because of opengl glDrawPixels
  size_t buf_pos = (width_*p.y + p.x);
  if (buf_pos >= colorbuffer_.size() || (int)buf_pos < 0) {
    std::cerr << "Fatal Error Renderer::write(Pixel p) : "
      << "pixel out of ppm_ : "
      << (int)p.x << "," << (int)p.y
      << std::endl;
  } else {
    colorbuffer_[buf_pos] = p.color;
  }

  ppm_.write(p);
}

Optional_hit Renderer::intersect(Ray const& ray) const{
  Optional_hit o;
  Optional_hit temp;
  std::vector<float> hits;

  for (std::vector<std::shared_ptr <Shape>>::const_iterator it = scene_.shapes.begin(); it != scene_.shapes.end(); ++it)
  {

    if (it == scene_.shapes.begin() || !o.hit)
    {
      o.hit = (*it)->intersect(ray, o.distance, o.intersection, o.normal);
      o.shape = &**it;
    }
    else
    {
      temp.hit = (*it)->intersect(ray, temp.distance, temp.intersection, temp.normal);
      temp.shape = &**it;
      if(o.distance > temp.distance && temp.distance > 0)
      {
        o = temp;
      }
    }

  }

  //std::cout << o.shape->get_name() << std::endl;

  return o;
}

Color Renderer::raytrace(Ray const& ray, int depth){
  Optional_hit o = intersect(ray);

  if(o.hit) return shade(ray, o, depth);
  else return scene_.ambient;
}

/*
Color Renderer::shade(Ray const& ray, Optional_hit const& o, int depth){ //braucht man noch color und recursion depth statt distance? wenn ja woher?

  Material temp_mat = scene_.material[o.shape->get_material()];

  float r = 0, g = 0, b = 0;
  float red = 0, green = 0, blue = 0;

  for(std::vector<Light_source>::const_iterator l = scene_.lights.begin(); l != scene_.lights.end(); ++l)
  {

    //Ray von Schnittpunkt zu Lichtquelle
    Ray lightray(o.intersection, glm::normalize((*l).get_position()));

    //Lichtintensität (Skalarprodukt, wird dann mit Reflexionskoeffizient und Helligkeit der Lichtquelle multipliziert)
    //oder Winkel zwischen Normale und Lichtquelle
    float tmp = glm::dot(o.normal, glm::normalize((*l).get_position()-o.intersection) );
    float angle_n_l = std::max(tmp, 0.0f);

    float temp_r = 0, temp_g = 0, temp_b = 0;

    Optional_hit shadow = intersect(lightray);
    if(!shadow.hit){

      /* Reflection ??
      //Winkel Kamera/Lichquelle
      float cam_light_angle = glm::dot(glm::normalize(o.intersection - scene_.cam.get_position()), glm::normalize((*l).get_position() - o.intersection));

      //Reflektionswinkel
      float reflection = cam_light_angle - (2* tmp);

      //Reflektionsvecktor
      glm::vec3 reflect_vec((2 * tmp * o.normal.x - (*l).get_position().x), (2 * tmp * o.normal.y - (*l).get_position().y), (2 * tmp * o.normal.z - (*l).get_position().z));

      //Ray reflection_ray(o.intersection, reflect_vec);
      //oder Ray reflection_ray = reflect_ray(o.intersection, o.normale, l.get_position()); ?

      Ray reflection_ray = reflect_ray(o.intersection, o.normal, (*l).get_position());

      temp_r = temp_mat.get_ks().r; //* pow(reflection, m);
      temp_g = temp_mat.get_ks().g; //* pow(reflection, m);
      temp_b = temp_mat.get_ks().b; //* pow(reflection, m);
      //......

      r += (*l).get_diffuse().r * (angle_n_l * temp_mat.get_kd().r + temp_mat.get_ks().r);
      g += (*l).get_diffuse().g * (angle_n_l * temp_mat.get_kd().g + temp_mat.get_ks().g);
      b += (*l).get_diffuse().b * (angle_n_l * temp_mat.get_kd().b + temp_mat.get_ks().b);

    }
    else{
      //Wenn im Schatten werden die Werde berechnet, sonst 0 ( Operator shadow.hit ? 1 : 0)
      r += temp_mat.get_kd().r * (*l).get_diffuse().r * angle_n_l;
      g += temp_mat.get_kd().g * (*l).get_diffuse().g * angle_n_l;
      b += temp_mat.get_kd().b * (*l).get_diffuse().b * angle_n_l;
    }

  }
  //mit Ambiente
  red = temp_mat.get_ka().r * scene_.ambient.r + r;
  green = temp_mat.get_ka().g * scene_.ambient.g + g;
  blue = temp_mat.get_ka().b * scene_.ambient.b + b;

  return Color(red, green, blue);

}*/

Color Renderer::shade(Ray const& ray, Optional_hit const& o, int depth){
  Color color; // Farbe des Strahls
  Ray rRay, tRay, sRay; // Reflexions-, Brechungs- und Schattenstrahlen
  Color rColor, tColor; // Farbe des reflektierten und gebrochenen Strahls
  Material temp_mat = scene_.material[o.shape->get_material()]; // Material des geschnittenen Shapes

  for (std::vector<Light_source>::const_iterator l = scene_.lights.begin(); l != scene_.lights.end(); ++l)
  {
    sRay = Ray(o.intersection, glm::normalize((*l).get_position()));
    //Teste ob Skalarprodukt von Normalen und sRay.direction positiv ist
    if(glm::dot(o.normal, sRay.direction) > 0){
      // Wieviel Licht wird von opaken und transparenten Flächen blockiert?
      Optional_hit shadow= intersect(sRay);
      float shading = glm::dot(o.normal, glm::normalize((*l).get_position()) );
      float shading_pos = std::max(shading, 0.0f);

      if (!shadow.hit)
      {
        color +=  (*l).get_diffuse() * (( temp_mat.get_kd() * shading_pos) + temp_mat.get_ks());
      }
      else{
        //Wenn im Schatten
        color +=  (*l).get_diffuse() * (( temp_mat.get_kd() * shading_pos));

      }

    }

  }

  if (depth <= 3)//3 = Max depth,
  {
    if (temp_mat.get_m() != 0)//Objekt reflektiert(spiegelt)
    {
      //Reflektionsray mit Reflektionsrichtung (ist der Einfallsvektor = Schnittpunkt?)
      rRay = reflect_ray(o.intersection, o.normal, o.intersection);
      rColor = raytrace(rRay, depth + 1);
      rColor *= temp_mat.get_m();
      //rColor *= temp_mat.get_ks();
      color += rColor;
    }

    if (temp_mat.get_opacity() != 0)//Objekt transparent(mit Refraktion)
    {
      //Ray in Brechungsrichtung
      tRay = Ray (o.intersection, (o.intersection + o.intersection * temp_mat.get_refract()));
      if(temp_mat.get_m() != 1)
        tColor = raytrace(tRay, depth + 1);
        tColor *= temp_mat.get_opacity();
        color += tColor;

    }
  }

  //ambiente Beleuchtung
  color += temp_mat.get_ka() * scene_.ambient;

  return color;
}

void Renderer::render_scene(std::string filename){

  //Scene wird geladen
  Sdf_loader loader{filename};
  scene_ = loader.load_scene(filename);

  //Daten aus Transferobjekt in den Renderer schreiben
  width_ = scene_.render.width;
  height_ = scene_.render.height;
  filename_= scene_.render.filename;
  std::vector<Color> buffer(width_*height_, Color(0.0, 0.0, 0.0));
  colorbuffer_=buffer;
  PpmWriter ppm(width_, height_);
  ppm_ = ppm;

  //Rays für das Bild gernerieren
  std::vector<Ray> rays;
  scene_.cam.generate_rays(width_, height_, rays);

  //Pixel für die Rays generieren
  std::vector<Pixel> pixel;
  for (unsigned i = 0; i < height_; ++i)
  {
    for (unsigned j = 0; j < width_; ++j)
    {
      Pixel p_temp(j,i);
      pixel.push_back(p_temp);
    }
  }

  std::vector<Pixel>::iterator j = pixel.begin();
  //Farbe für jeden Pixel berechnen
  for (std::vector<Ray>::iterator i = rays.begin(); i < rays.end(); ++i)
  {
    Color temp = raytrace(*i,1);
    (*j).color = temp;
    //std::cout << temp;
    write(*j);
    ++j;
  }
  ppm_.save(filename_);

}

Ray Renderer::reflect_ray(glm::vec3 const& intersection, glm::vec3 const& normale, glm::vec3 const& rayDirection) const{
	glm::vec3 spiegel{0.0f, 0.0f, 0.0f}; //neuer Ray direction kommt hier rein, origin ist intersection
	spiegel.x = (2*normale.x*normale.x*rayDirection.x + 2*normale.x*normale.y*rayDirection.y + 2*normale.x*normale.z*rayDirection.z - rayDirection.x);
	spiegel.y = (2*normale.x*normale.y*rayDirection.x + 2*normale.x*normale.y*rayDirection.y + 2*normale.y*normale.z*rayDirection.z - rayDirection.y);
	spiegel.z = (2*normale.y*normale.z*rayDirection.x + 2*normale.y*normale.z*rayDirection.y + 2*normale.z*normale.z*rayDirection.z - rayDirection.z);
	Ray newRay{intersection, spiegel}; //spiegel muss vielleicht *-1 genommen werden, bin mir nicht sicher ob der in die richtige Richtung zeigt
	return newRay;

}
<|endoftext|>


<commit_before>//===-- Internalize.cpp - Mark functions internal -------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass loops over all of the functions in the input module, looking for a
// main function.  If a main function is found, all other functions and all
// global variables with initializers are marked as internal.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/Pass.h"
#include "llvm/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/Statistic.h"
#include <fstream>
#include <set>
using namespace llvm;

namespace {
  Statistic<> NumFunctions("internalize", "Number of functions internalized");
  Statistic<> NumGlobals  ("internalize", "Number of global vars internalized");

  // APIFile - A file which contains a list of symbols that should not be marked
  // external.
  cl::opt<std::string>
  APIFile("internalize-public-api-file", cl::value_desc("filename"),
          cl::desc("A file containing list of symbol names to preserve"));

  // APIList - A list of symbols that should not be marked internal.
  cl::list<std::string>
  APIList("internalize-public-api-list", cl::value_desc("list"),
          cl::desc("A list of symbol names to preserve"),
          cl::CommaSeparated);

  class InternalizePass : public ModulePass {
    std::set<std::string> ExternalNames;
    bool DontInternalize;
  public:
    InternalizePass(bool InternalizeEverything = true) : DontInternalize(false){
      if (!APIFile.empty())           // If a filename is specified, use it
        LoadFile(APIFile.c_str());
      else if (!APIList.empty())      // Else, if a list is specified, use it.
        ExternalNames.insert(APIList.begin(), APIList.end());
      else if (!InternalizeEverything)
        // Finally, if we're allowed to, internalize all but main.
        DontInternalize = true;
    }

    void LoadFile(const char *Filename) {
      // Load the APIFile...
      std::ifstream In(Filename);
      if (!In.good()) {
        std::cerr << "WARNING: Internalize couldn't load file '" << Filename
                  << "'!\n";
        return;   // Do not internalize anything...
      }
      while (In) {
        std::string Symbol;
        In >> Symbol;
        if (!Symbol.empty())
          ExternalNames.insert(Symbol);
      }
    }

    virtual bool runOnModule(Module &M) {
      if (DontInternalize) return false;

      // If no list or file of symbols was specified, check to see if there is a
      // "main" symbol defined in the module.  If so, use it, otherwise do not
      // internalize the module, it must be a library or something.
      //
      if (ExternalNames.empty()) {
        Function *MainFunc = M.getMainFunction();
        if (MainFunc == 0 || MainFunc->isExternal())
          return false;  // No main found, must be a library...

        // Preserve main, internalize all else.
        ExternalNames.insert(MainFunc->getName());
      }

      bool Changed = false;

      // Found a main function, mark all functions not named main as internal.
      for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
        if (!I->isExternal() &&         // Function must be defined here
            !I->hasInternalLinkage() &&  // Can't already have internal linkage
            !ExternalNames.count(I->getName())) {// Not marked to keep external?
          I->setLinkage(GlobalValue::InternalLinkage);
          Changed = true;
          ++NumFunctions;
          DEBUG(std::cerr << "Internalizing func " << I->getName() << "\n");
        }

      // Mark all global variables with initializers as internal as well...
      for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
        if (!I->isExternal() && !I->hasInternalLinkage() &&
            !ExternalNames.count(I->getName())) {
          // Special case handling of the global ctor and dtor list.  When we
          // internalize it, we mark it constant, which allows elimination of
          // the list if it's empty.
          //
          if (I->hasAppendingLinkage() && (I->getName() == "llvm.global_ctors"||
                                           I->getName() == "llvm.global_dtors"))
            I->setConstant(true);

          I->setLinkage(GlobalValue::InternalLinkage);
          Changed = true;
          ++NumGlobals;
          DEBUG(std::cerr << "Internalizing gvar " << I->getName() << "\n");
        }

      return Changed;
    }
  };

  RegisterOpt<InternalizePass> X("internalize", "Internalize Global Symbols");
} // end anonymous namespace

ModulePass *llvm::createInternalizePass(bool InternalizeEverything) {
  return new InternalizePass(InternalizeEverything);
}
<commit_msg>Wrap a long line, never internalize llvm.used.<commit_after>//===-- Internalize.cpp - Mark functions internal -------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass loops over all of the functions in the input module, looking for a
// main function.  If a main function is found, all other functions and all
// global variables with initializers are marked as internal.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/Pass.h"
#include "llvm/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/Statistic.h"
#include <fstream>
#include <set>
using namespace llvm;

namespace {
  Statistic<> NumFunctions("internalize", "Number of functions internalized");
  Statistic<> NumGlobals  ("internalize", "Number of global vars internalized");

  // APIFile - A file which contains a list of symbols that should not be marked
  // external.
  cl::opt<std::string>
  APIFile("internalize-public-api-file", cl::value_desc("filename"),
          cl::desc("A file containing list of symbol names to preserve"));

  // APIList - A list of symbols that should not be marked internal.
  cl::list<std::string>
  APIList("internalize-public-api-list", cl::value_desc("list"),
          cl::desc("A list of symbol names to preserve"),
          cl::CommaSeparated);

  class InternalizePass : public ModulePass {
    std::set<std::string> ExternalNames;
    bool DontInternalize;
  public:
    InternalizePass(bool InternalizeEverything = true) : DontInternalize(false){
      if (!APIFile.empty())           // If a filename is specified, use it
        LoadFile(APIFile.c_str());
      else if (!APIList.empty())      // Else, if a list is specified, use it.
        ExternalNames.insert(APIList.begin(), APIList.end());
      else if (!InternalizeEverything)
        // Finally, if we're allowed to, internalize all but main.
        DontInternalize = true;
    }

    void LoadFile(const char *Filename) {
      // Load the APIFile...
      std::ifstream In(Filename);
      if (!In.good()) {
        std::cerr << "WARNING: Internalize couldn't load file '" << Filename
                  << "'!\n";
        return;   // Do not internalize anything...
      }
      while (In) {
        std::string Symbol;
        In >> Symbol;
        if (!Symbol.empty())
          ExternalNames.insert(Symbol);
      }
    }

    virtual bool runOnModule(Module &M) {
      if (DontInternalize) return false;

      // If no list or file of symbols was specified, check to see if there is a
      // "main" symbol defined in the module.  If so, use it, otherwise do not
      // internalize the module, it must be a library or something.
      //
      if (ExternalNames.empty()) {
        Function *MainFunc = M.getMainFunction();
        if (MainFunc == 0 || MainFunc->isExternal())
          return false;  // No main found, must be a library...

        // Preserve main, internalize all else.
        ExternalNames.insert(MainFunc->getName());
      }

      bool Changed = false;

      // Found a main function, mark all functions not named main as internal.
      for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
        if (!I->isExternal() &&         // Function must be defined here
            !I->hasInternalLinkage() &&  // Can't already have internal linkage
            !ExternalNames.count(I->getName())) {// Not marked to keep external?
          I->setLinkage(GlobalValue::InternalLinkage);
          Changed = true;
          ++NumFunctions;
          DEBUG(std::cerr << "Internalizing func " << I->getName() << "\n");
        }

      // Mark all global variables with initializers as internal as well...
      for (Module::global_iterator I = M.global_begin(), E = M.global_end();
           I != E; ++I)
        if (!I->isExternal() && !I->hasInternalLinkage() &&
            !ExternalNames.count(I->getName()) &&
            // *never* internalize the llvm.used symbol, used to implement
            // attribute((used)).
            I->getName() != "llvm.used") {
          // Special case handling of the global ctor and dtor list.  When we
          // internalize it, we mark it constant, which allows elimination of
          // the list if it's empty.
          //
          if (I->hasAppendingLinkage() && (I->getName() == "llvm.global_ctors"||
                                           I->getName() == "llvm.global_dtors"))
            I->setConstant(true);

          I->setLinkage(GlobalValue::InternalLinkage);
          Changed = true;
          ++NumGlobals;
          DEBUG(std::cerr << "Internalizing gvar " << I->getName() << "\n");
        }

      return Changed;
    }
  };

  RegisterOpt<InternalizePass> X("internalize", "Internalize Global Symbols");
} // end anonymous namespace

ModulePass *llvm::createInternalizePass(bool InternalizeEverything) {
  return new InternalizePass(InternalizeEverything);
}
<|endoftext|>


<commit_before>#include <string>
#include <cstring>
#include <vector>
#include "math3d/math3d.h"

#include "pbge/pbge.h"

#include "Ellipsoids.h"

Ellipsoids::Ellipsoids(pbge::GraphicAPI * _gfx, int total_ellipsoids) {
    std::vector<pbge::Model*> _models;
    _models.push_back(pbge::Geometrics::createSphere(1.0f, 10, _gfx));
    _models.push_back(pbge::Geometrics::createSphere(1.0f, 7, _gfx));
    _models.push_back(pbge::Geometrics::createSphere(1.0f, 5, _gfx));
    _models.push_back(pbge::Geometrics::createSphere(1.0f, 4, _gfx));
    _models.push_back(pbge::Geometrics::createSphere(1.0f, 3, _gfx));
    _models.push_back(pbge::Geometrics::createSphere(1.0f, 2, _gfx));
    std::vector<float> distances;
    distances.push_back(10.0f);
    distances.push_back(20.0f);
    distances.push_back(35.0f);
    distances.push_back(60.0f);
    distances.push_back(100.0f);
    this->models = new LODModels(_models, distances);
    this->gfx = _gfx;
    this->tex = gfx->getFactory()->createTextureBuffer(total_ellipsoids * sizeof(math3d::matrix44));
    this->added_ellipsoids = 0;
    this->render_pass_program = NULL;
    this->depth_pass_program = NULL;
    this->peeling_program = NULL;
    this->transformation_shader = NULL;
}

PeelingAwareCollection * Ellipsoids::createEllipsoids(unsigned number_of_ellipsoids, math3d::matrix44 * transforms, BoundingBox box) {
    void * texData = tex->getBuffer()->map(pbge::Buffer::WRITE_ONLY);
    memcpy((unsigned char *)texData + this->added_ellipsoids * sizeof(math3d::matrix44), transforms, number_of_ellipsoids * sizeof(math3d::matrix44));
    tex->getBuffer()->unmap();
    texData = NULL;
    tex->setInternalFormat(pbge::Texture::FLOAT, pbge::Texture::RGBA);
    PeelingAwareCollection * ellipsoids = new PeelingAwareCollection(models, get_peeling_program());
    ellipsoids->setNumberOfInstances(number_of_ellipsoids);

    pbge::UniformBufferSampler * uniform = ellipsoids->getUniformSet()->getBufferSampler("transforms");
    uniform->setValue(tex);
    ellipsoids->setTransforms(transforms);

    pbge::UniformFloat * base_instance = ellipsoids->getUniformSet()->getFloat("base_instance");
    base_instance->setValue((float)this->added_ellipsoids);
    this->added_ellipsoids += number_of_ellipsoids;

	ellipsoids->setRenderPassProgram(get_render_pass_program());
    ellipsoids->setDepthPassProgram(get_depth_pass_program());
    ellipsoids->setBoundingBox(box);
    return ellipsoids;
}

pbge::Shader * Ellipsoids::get_transformation_shader() {
    if(this->transformation_shader == NULL) {
        this->transformation_shader = gfx->getFactory()->createShaderFromString(
            "#version 150\n"
		    "uniform samplerBuffer transforms;\n"
            "uniform float base_instance;\n"
            "uniform float scale;\n"
            "uniform mat4 pbge_ModelViewMatrix;\n"
            "uniform float alpha_index;\n"
            "in  vec4 pbge_Vertex;\n"
            "void calc_transformations(out vec4 view_position, out vec3 view_normal, out vec4 color, out mat4 view_transform) {\n"
            "   int index = (int(base_instance) + gl_InstanceID) * 4;\n"
            "   vec4 vertex = vec4(pbge_Vertex.xyz * scale, 1.0);\n"
		    "   vec4 col1 = texelFetch(transforms, index);\n"
		    "   vec4 col2 = texelFetch(transforms, index + 1);\n"
		    "   vec4 col3 = texelFetch(transforms, index + 2);\n"
		    "   vec4 col4 = texelFetch(transforms, index + 3);\n"
		    "   color = vec4(col1.w,col2.w,col3.w,col4.w);\n"
            "   color = vec4(1,1,1,color[int(alpha_index)]);\n"
            "   col1 = vec4(col1.xyz, 0);\n"
		    "   col2 = vec4(col2.xyz, 0);\n"
		    "   col3 = vec4(col3.xyz, 0);\n"
		    "   col4 = vec4(col4.xyz, 1);\n"
		    "   mat4 transformation = mat4(col1, col2, col3, col4);\n"
		    "   view_transform = pbge_ModelViewMatrix * transformation;\n"
		    "   vec4 _normal = inverse(transpose(view_transform)) * pbge_Vertex;\n"
		    "   view_normal = normalize(_normal.xyz);\n"
		    "   view_position = view_transform * vertex;\n"
            "}",
            pbge::Shader::VERTEX_SHADER);
    }
    return this->transformation_shader;
}

pbge::GPUProgram * Ellipsoids::get_render_pass_program() {
    if(this->render_pass_program == NULL) {
        pbge::Shader * vertex_shader = gfx->getFactory()->createShaderFromString(
            "#version 150\n"
            "uniform mat4 pbge_ProjectionMatrix;\n"
            "out vec4 position;\n"
		    "out vec3 normal;\n"
		    "out vec4 lightPosition;\n"
		    "void calc_transformations(out vec4 view_position, out vec3 view_normal, out vec4 color, out mat4 view_tranform);\n"
            "void main() {\n"
		    "   mat4 view_transform;\n"
            "   const vec4 light_position = vec4(16,16,16,1);\n"
            "   calc_transformations(position, normal, gl_FrontColor, view_transform);\n"
            "   lightPosition = view_transform * light_position;\n"
		    "   gl_Position = pbge_ProjectionMatrix * position;\n"
		    "}",
            pbge::Shader::VERTEX_SHADER);
        pbge::Shader * frag_shader = gfx->getFactory()->createShaderFromString(
            "uniform float min_alpha;\n"
            "uniform float max_alpha;\n"
            "uniform vec4 min_color;\n"
            "uniform vec4 max_color;\n"
            "in vec4 position;\n"
		    "in vec3 normal;\n"
		    "in vec4 lightPosition;\n"
		    "void main() {\n"
            "   float alpha = gl_Color.a;\n"
            "   if(alpha <= min_alpha - 0.005) discard;\n"
            "   if(alpha >= max_alpha + 0.005) discard;\n"
            "   float rampIndex = (alpha - min_alpha) / max(max_alpha - min_alpha - 0.6,0.1);"
            "   vec4 diffuseColor = mix(min_color, max_color, rampIndex);\n"
            "   vec4 lightDiffuseColor = vec4(2,2,2,2);\n"
		    "   vec3 lightDir = normalize((lightPosition - position).xyz);\n"
		    "   float intensity = max(0.0, dot(lightDir, normal));\n"
		    "   gl_FragData[0] = vec4(diffuseColor.rgb * lightDiffuseColor.rgb * intensity, alpha);\n"
            "}",
            pbge::Shader::FRAGMENT_SHADER);
        std::vector<pbge::Shader *> vertex_shaders;
        std::vector<pbge::Shader *> fragment_shaders;

        vertex_shaders.push_back(vertex_shader);
        vertex_shaders.push_back(get_transformation_shader());
        fragment_shaders.push_back(frag_shader);
        this->render_pass_program = gfx->getFactory()->createProgram(
            vertex_shaders,
            fragment_shaders
            );
    }
    return this->render_pass_program;
}

pbge::GPUProgram * Ellipsoids::get_depth_pass_program() {
    if(this->depth_pass_program == NULL) {
        pbge::Shader * vertex_shader = gfx->getFactory()->createShaderFromString(
            "#version 150\n"
            "uniform mat4 pbge_ProjectionMatrix;\n"
            "out vec4 position;\n"
		    "out vec3 normal;\n"
		    "out vec4 lightPosition;\n"
		    "void calc_transformations(out vec4 view_position, out vec3 view_normal, out vec4 color, out mat4 view_tranform);\n"
            "void main() {\n"
		    "   mat4 view_transform;\n"
            "   calc_transformations(position, normal, gl_FrontColor, view_transform);\n"
            "   gl_Position = pbge_ProjectionMatrix * position;\n"
		    "}",
            pbge::Shader::VERTEX_SHADER);
        pbge::Shader * frag_shader = gfx->getFactory()->createShaderFromString(
            "",
            pbge::Shader::FRAGMENT_SHADER);
        std::vector<pbge::Shader *> vertex_shaders;
        std::vector<pbge::Shader *> fragment_shaders;

        vertex_shaders.push_back(vertex_shader);
        vertex_shaders.push_back(get_transformation_shader());
        fragment_shaders.push_back(frag_shader);
        this->depth_pass_program = gfx->getFactory()->createProgram(
            vertex_shaders,
            fragment_shaders
            );
    }
    return this->depth_pass_program;
}

pbge::GPUProgram * Ellipsoids::get_peeling_program() {
    if(this->peeling_program == NULL) {
        pbge::Shader * vertex_shader = gfx->getFactory()->createShaderFromString(
            "#version 150\n"
		    "uniform mat4 pbge_ProjectionMatrix;\n"
		    "out vec4 position;\n"
            "out vec4 nposition;\n"
		    "out vec3 normal;\n"
		    "out vec4 lightPosition;\n"
            "void calc_transformations(out vec4 view_position, out vec3 view_normal, out vec4 color, out mat4 view_tranform);\n"
            "void main() {\n"
            "   mat4 view_transform;\n"
            "   calc_transformations(position, normal, gl_FrontColor, view_transform);\n"
		    "   const vec4 light_position = vec4(16,16,16,1);\n"
            "   lightPosition = view_transform * light_position;\n"
            "   nposition = pbge_ProjectionMatrix * position;\n"
		    "   gl_Position = nposition;\n"
		    "}",
            pbge::Shader::VERTEX_SHADER);
        pbge::Shader * frag_shader = gfx->getFactory()->createShaderFromString(
            "in vec4 position;\n"
		    "in vec3 normal;\n"
		    "in vec4 lightPosition;\n"
            "in vec4 nposition;\n"
            "uniform sampler2D depth;\n"
            "uniform float min_alpha;\n"
            "uniform float max_alpha;\n"
            "uniform vec4 min_color;\n"
            "uniform vec4 max_color;\n"
		    "void main() {\n"
            // nposition is in ndc so we need to do the perspective division to transform the position
            // to the range -1 to 1.
            "   vec2 p = 0.5 * (nposition.xy / nposition.w) + 0.5;\n"
            "   float alpha = gl_Color.a;\n"
            // depth + offset to avoid z-fighting
            "   if(gl_FragCoord.z <= (texture2D(depth,p.xy)).r + 0.0001) discard;\n"
            "   if(normal.z >= 0) discard;\n"
            "   if(alpha <= min_alpha - 0.005) discard;\n"
            "   if(alpha >= max_alpha + 0.005) discard;\n"
            "   float rampIndex = (alpha - min_alpha) / max(max_alpha - min_alpha - 0.6,0.1);"
            "   vec4 diffuseColor = mix(min_color, max_color, rampIndex);\n"
            "   vec4 lightDiffuseColor = vec4(2,2,2,2);\n"
		    "   vec3 lightDir = normalize((lightPosition - position).xyz);\n"
		    "   float intensity = max(0.0, dot(lightDir, normal));\n"
		    "   gl_FragData[0] = vec4(diffuseColor.rgb * lightDiffuseColor.rgb * intensity, alpha);\n"
            "}",
            pbge::Shader::FRAGMENT_SHADER);
        std::vector<pbge::Shader *> vertex_shaders;
        std::vector<pbge::Shader *> fragment_shaders;

        vertex_shaders.push_back(vertex_shader);
        vertex_shaders.push_back(get_transformation_shader());
        fragment_shaders.push_back(frag_shader);
        this->peeling_program = gfx->getFactory()->createProgram(
            vertex_shaders,
            fragment_shaders
            );
    }
    return this->peeling_program;
}<commit_msg>Enhancing lights on tensor field<commit_after>#include <string>
#include <cstring>
#include <vector>
#include "math3d/math3d.h"

#include "pbge/pbge.h"

#include "Ellipsoids.h"

Ellipsoids::Ellipsoids(pbge::GraphicAPI * _gfx, int total_ellipsoids) {
    std::vector<pbge::Model*> _models;
    _models.push_back(pbge::Geometrics::createSphere(1.0f, 10, _gfx));
    _models.push_back(pbge::Geometrics::createSphere(1.0f, 7, _gfx));
    _models.push_back(pbge::Geometrics::createSphere(1.0f, 5, _gfx));
    _models.push_back(pbge::Geometrics::createSphere(1.0f, 4, _gfx));
    _models.push_back(pbge::Geometrics::createSphere(1.0f, 3, _gfx));
    _models.push_back(pbge::Geometrics::createSphere(1.0f, 2, _gfx));
    std::vector<float> distances;
    distances.push_back(10.0f);
    distances.push_back(20.0f);
    distances.push_back(35.0f);
    distances.push_back(60.0f);
    distances.push_back(100.0f);
    this->models = new LODModels(_models, distances);
    this->gfx = _gfx;
    this->tex = gfx->getFactory()->createTextureBuffer(total_ellipsoids * sizeof(math3d::matrix44));
    this->added_ellipsoids = 0;
    this->render_pass_program = NULL;
    this->depth_pass_program = NULL;
    this->peeling_program = NULL;
    this->transformation_shader = NULL;
}

PeelingAwareCollection * Ellipsoids::createEllipsoids(unsigned number_of_ellipsoids, math3d::matrix44 * transforms, BoundingBox box) {
    void * texData = tex->getBuffer()->map(pbge::Buffer::WRITE_ONLY);
    memcpy((unsigned char *)texData + this->added_ellipsoids * sizeof(math3d::matrix44), transforms, number_of_ellipsoids * sizeof(math3d::matrix44));
    tex->getBuffer()->unmap();
    texData = NULL;
    tex->setInternalFormat(pbge::Texture::FLOAT, pbge::Texture::RGBA);
    PeelingAwareCollection * ellipsoids = new PeelingAwareCollection(models, get_peeling_program());
    ellipsoids->setNumberOfInstances(number_of_ellipsoids);

    pbge::UniformBufferSampler * uniform = ellipsoids->getUniformSet()->getBufferSampler("transforms");
    uniform->setValue(tex);
    ellipsoids->setTransforms(transforms);

    pbge::UniformFloat * base_instance = ellipsoids->getUniformSet()->getFloat("base_instance");
    base_instance->setValue((float)this->added_ellipsoids);
    this->added_ellipsoids += number_of_ellipsoids;

	ellipsoids->setRenderPassProgram(get_render_pass_program());
    ellipsoids->setDepthPassProgram(get_depth_pass_program());
    ellipsoids->setBoundingBox(box);
    return ellipsoids;
}

pbge::Shader * Ellipsoids::get_transformation_shader() {
    if(this->transformation_shader == NULL) {
        this->transformation_shader = gfx->getFactory()->createShaderFromString(
            "#version 150\n"
		    "uniform samplerBuffer transforms;\n"
            "uniform float base_instance;\n"
            "uniform float scale;\n"
            "uniform mat4 pbge_ModelViewMatrix;\n"
            "uniform float alpha_index;\n"
            "in  vec4 pbge_Vertex;\n"
            "void calc_transformations(out vec4 view_position, out vec3 view_normal, out vec4 color, out mat4 view_transform) {\n"
            "   int index = (int(base_instance) + gl_InstanceID) * 4;\n"
            "   vec4 vertex = vec4(pbge_Vertex.xyz * scale, 1.0);\n"
		    "   vec4 col1 = texelFetch(transforms, index);\n"
		    "   vec4 col2 = texelFetch(transforms, index + 1);\n"
		    "   vec4 col3 = texelFetch(transforms, index + 2);\n"
		    "   vec4 col4 = texelFetch(transforms, index + 3);\n"
		    "   color = vec4(col1.w,col2.w,col3.w,col4.w);\n"
            "   color = vec4(1,1,1,color[int(alpha_index)]);\n"
            "   col1 = vec4(col1.xyz, 0);\n"
		    "   col2 = vec4(col2.xyz, 0);\n"
		    "   col3 = vec4(col3.xyz, 0);\n"
		    "   col4 = vec4(col4.xyz, 1);\n"
		    "   mat4 transformation = mat4(col1, col2, col3, col4);\n"
		    "   view_transform = pbge_ModelViewMatrix * transformation;\n"
		    "   vec4 _normal = inverse(transpose(view_transform)) * pbge_Vertex;\n"
		    "   view_normal = normalize(_normal.xyz);\n"
		    "   view_position = view_transform * vertex;\n"
            "}",
            pbge::Shader::VERTEX_SHADER);
    }
    return this->transformation_shader;
}

pbge::GPUProgram * Ellipsoids::get_render_pass_program() {
    if(this->render_pass_program == NULL) {
        pbge::Shader * vertex_shader = gfx->getFactory()->createShaderFromString(
            "#version 150\n"
            "uniform mat4 pbge_ProjectionMatrix;\n"
            "out vec4 position;\n"
		    "out vec3 normal;\n"
		    "out vec4 lightPosition;\n"
		    "void calc_transformations(out vec4 view_position, out vec3 view_normal, out vec4 color, out mat4 view_tranform);\n"
            "void main() {\n"
		    "   mat4 view_transform;\n"
            "   const vec4 light_position = vec4(0,16,16,1);\n"
            "   calc_transformations(position, normal, gl_FrontColor, view_transform);\n"
            "   lightPosition = pbge_ProjectionMatrix * view_transform * light_position;\n"
		    "   gl_Position = pbge_ProjectionMatrix * position;\n"
		    "}",
            pbge::Shader::VERTEX_SHADER);
        pbge::Shader * frag_shader = gfx->getFactory()->createShaderFromString(
            "uniform float min_alpha;\n"
            "uniform float max_alpha;\n"
            "uniform vec4 min_color;\n"
            "uniform vec4 max_color;\n"
            "in vec4 position;\n"
		    "in vec3 normal;\n"
		    "in vec4 lightPosition;\n"
		    "void main() {\n"
            "   float alpha = gl_Color.a;\n"
            "   if(alpha <= min_alpha - 0.005) discard;\n"
            "   if(alpha >= max_alpha + 0.005) discard;\n"
            "   float rampIndex = (alpha - min_alpha) / max(max_alpha - min_alpha - 0.6,0.1);"
            "   vec4 diffuseColor = mix(min_color, max_color, rampIndex);\n"
            "   vec4 lightDiffuseColor = vec4(2,2,2,2);\n"
		    "   vec3 lightDir = normalize((lightPosition - position).xyz);\n"
		    "   float intensity = max(0.0, dot(lightDir, normal));\n"
		    "   gl_FragData[0] = vec4(diffuseColor.rgb * lightDiffuseColor.rgb * intensity, alpha);\n"
            "}",
            pbge::Shader::FRAGMENT_SHADER);
        std::vector<pbge::Shader *> vertex_shaders;
        std::vector<pbge::Shader *> fragment_shaders;

        vertex_shaders.push_back(vertex_shader);
        vertex_shaders.push_back(get_transformation_shader());
        fragment_shaders.push_back(frag_shader);
        this->render_pass_program = gfx->getFactory()->createProgram(
            vertex_shaders,
            fragment_shaders
            );
    }
    return this->render_pass_program;
}

pbge::GPUProgram * Ellipsoids::get_depth_pass_program() {
    if(this->depth_pass_program == NULL) {
        pbge::Shader * vertex_shader = gfx->getFactory()->createShaderFromString(
            "#version 150\n"
            "uniform mat4 pbge_ProjectionMatrix;\n"
            "out vec4 position;\n"
		    "out vec3 normal;\n"
		    "out vec4 lightPosition;\n"
		    "void calc_transformations(out vec4 view_position, out vec3 view_normal, out vec4 color, out mat4 view_tranform);\n"
            "void main() {\n"
		    "   mat4 view_transform;\n"
            "   calc_transformations(position, normal, gl_FrontColor, view_transform);\n"
            "   gl_Position = pbge_ProjectionMatrix * position;\n"
		    "}",
            pbge::Shader::VERTEX_SHADER);
        pbge::Shader * frag_shader = gfx->getFactory()->createShaderFromString(
            "",
            pbge::Shader::FRAGMENT_SHADER);
        std::vector<pbge::Shader *> vertex_shaders;
        std::vector<pbge::Shader *> fragment_shaders;

        vertex_shaders.push_back(vertex_shader);
        vertex_shaders.push_back(get_transformation_shader());
        fragment_shaders.push_back(frag_shader);
        this->depth_pass_program = gfx->getFactory()->createProgram(
            vertex_shaders,
            fragment_shaders
            );
    }
    return this->depth_pass_program;
}

pbge::GPUProgram * Ellipsoids::get_peeling_program() {
    if(this->peeling_program == NULL) {
        pbge::Shader * vertex_shader = gfx->getFactory()->createShaderFromString(
            "#version 150\n"
		    "uniform mat4 pbge_ProjectionMatrix;\n"
		    "out vec4 position;\n"
            "out vec4 nposition;\n"
		    "out vec3 normal;\n"
		    "out vec4 lightPosition;\n"
            "void calc_transformations(out vec4 view_position, out vec3 view_normal, out vec4 color, out mat4 view_tranform);\n"
            "void main() {\n"
            "   mat4 view_transform;\n"
            "   calc_transformations(position, normal, gl_FrontColor, view_transform);\n"
		    "   const vec4 light_position = vec4(0,16,16,1);\n"
            "   lightPosition = pbge_ProjectionMatrix * view_transform * light_position;\n"
            "   nposition = pbge_ProjectionMatrix * position;\n"
		    "   gl_Position = nposition;\n"
		    "}",
            pbge::Shader::VERTEX_SHADER);
        pbge::Shader * frag_shader = gfx->getFactory()->createShaderFromString(
            "in vec4 position;\n"
		    "in vec3 normal;\n"
		    "in vec4 lightPosition;\n"
            "in vec4 nposition;\n"
            "uniform sampler2D depth;\n"
            "uniform float min_alpha;\n"
            "uniform float max_alpha;\n"
            "uniform vec4 min_color;\n"
            "uniform vec4 max_color;\n"
		    "void main() {\n"
            // nposition is in ndc so we need to do the perspective division to transform the position
            // to the range -1 to 1.
            "   vec2 p = 0.5 * (nposition.xy / nposition.w) + 0.5;\n"
            "   float alpha = gl_Color.a;\n"
            // depth + offset to avoid z-fighting
            "   if(gl_FragCoord.z <= (texture2D(depth,p.xy)).r + 0.0001) discard;\n"
            "   if(normal.z >= 0) discard;\n"
            "   if(alpha <= min_alpha - 0.005) discard;\n"
            "   if(alpha >= max_alpha + 0.005) discard;\n"
            "   float rampIndex = (alpha - min_alpha) / max(max_alpha - min_alpha - 0.6,0.1);"
            "   vec4 diffuseColor = mix(min_color, max_color, rampIndex);\n"
            "   vec4 lightDiffuseColor = vec4(2,2,2,2);\n"
		    "   vec3 lightDir = normalize((lightPosition - position).xyz);\n"
		    "   float intensity = max(0.0, dot(lightDir, normal));\n"
		    "   gl_FragData[0] = vec4(diffuseColor.rgb * lightDiffuseColor.rgb * intensity, alpha);\n"
            "}",
            pbge::Shader::FRAGMENT_SHADER);
        std::vector<pbge::Shader *> vertex_shaders;
        std::vector<pbge::Shader *> fragment_shaders;

        vertex_shaders.push_back(vertex_shader);
        vertex_shaders.push_back(get_transformation_shader());
        fragment_shaders.push_back(frag_shader);
        this->peeling_program = gfx->getFactory()->createProgram(
            vertex_shaders,
            fragment_shaders
            );
    }
    return this->peeling_program;
}<|endoftext|>


<commit_before>// -----------------------------------------------------------------------------
// Copyright  : (C) 2014 Andreas-C. Bernstein
// License    : MIT (see the file LICENSE)
// Maintainer : Andreas-C. Bernstein <andreas.bernstein@uni-weimar.de>
// Stability  : experimental
//
// Renderer
// -----------------------------------------------------------------------------

#include "renderer.hpp"
#include "optional_hit.hpp"
#include "ray.hpp"
#include "scene.hpp"
#include "camera.hpp"
#include "sdf_loader.hpp"
#include "color.hpp"
#include "shape.hpp"
#include <algorithm> // min_element

Renderer::Renderer(unsigned w, unsigned h, std::string const& file):
	width_(w),
	height_(h),
	colorbuffer_(w*h, Color(0.0, 0.0, 0.0)),
	filename_(file),
	ppm_(width_, height_)
	{}

Renderer::Renderer():
	width_(0),
	height_(0),
	colorbuffer_(0, Color(0.0, 0.0, 0.0)),
	filename_(""),
	ppm_(width_, height_)
	{}

unsigned Renderer::get_width() const{
  return width_;
}
unsigned Renderer::get_height() const{
  return height_;
}
std::string Renderer::get_filename() const{
  return filename_;
}
Scene Renderer::get_scene() const{
  return scene_;
}

Renderer& Renderer::operator= (Renderer const& rhs){
  width_ = rhs.get_width();
  height_ = rhs.get_height();
  filename_ = rhs.get_filename();
  return *this;
}

void Renderer::render()
{
  const std::size_t checkersize = 20;

  for (unsigned y = 0; y < height_; ++y) {
    for (unsigned x = 0; x < width_; ++x) {
      Pixel p(x,y);
      if ( ((x/checkersize)%2) != ((y/checkersize)%2)) {
        p.color = Color(0.0, 1.0, float(x)/height_);
      } else {
        p.color = Color(1.0, 0.0, float(y)/width_);
      }

      write(p);
    }
  }
  ppm_.save(filename_);
}

void Renderer::write(Pixel const& p)
{
  // flip pixels, because of opengl glDrawPixels
  size_t buf_pos = (width_*p.y + p.x);
  if (buf_pos >= colorbuffer_.size() || (int)buf_pos < 0) {
    std::cerr << "Fatal Error Renderer::write(Pixel p) : "
      << "pixel out of ppm_ : "
      << (int)p.x << "," << (int)p.y
      << std::endl;
  } else {
    colorbuffer_[buf_pos] = p.color;
  }

  ppm_.write(p);
}

Optional_hit Renderer::intersect(Ray const& ray) const{
  Optional_hit o;
  std::vector<float> dis;
  float distance;

  for (std::vector<std::shared_ptr <Shape>>::const_iterator it = scene_.shapes.begin(); it != scene_.shapes.end(); ++it)
  {
    std::shared_ptr <Shape> s_ptr = *it;
    //Shape s = *s_ptr;
    s_ptr->intersect_optional(ray, distance, o.intersection, o.normal);
    dis.push_back(distance);
  }

  //suche geringste distance und passendes Shape dazu
  int min_pos = std::distance(dis.begin(), std::min_element(dis.begin(), dis.end()));
  //std::cout << "test intersect" << std::endl;
  o.shape = &*scene_.shapes[min_pos];
  o.distance = *std::min_element(dis.begin(), dis.end());

  //normal, ... berechnen

  return o;
}

Color Renderer::raytrace(Ray const& ray){
  Optional_hit o = intersect(ray);
  //std::cout << "test raytrace" << std::endl;
  if(o.distance == 0){ //ehemalige depth
    return scene_.ambient;
  }

  if(o.hit) {

    Light_source l{"licht", {0,0,0}, {1.0,1.0,1.0}, {0.4,0.4,0.4}};
    float tmp = glm::dot(glm::normalize(ray.direction), glm::normalize(l.get_position() - o.intersection)); //intersection ausrechnen lassen bei intersect!
    Material temp_mat = scene_.material[(*o.shape).get_material()];
    float red = temp_mat.get_kd().r * l.get_diffuse().r * tmp;
    float green = temp_mat.get_kd().g * l.get_diffuse().g * tmp;
    float blue = temp_mat.get_kd().b * l.get_diffuse().b * tmp;
    return Color(red, green, blue);

  }
  else {
    return scene_.ambient;
  }

}

//ungefähres Prozedere? was ist mit den Methoden vom Bernstein?
void Renderer::render_scene(std::string filename){

  //Scene wird geladen
  Sdf_loader loader{filename};
  scene_ = loader.load_scene(filename);

  //Daten aus Transferobejkt in den Renderer schreiben
  width_ = scene_.render.width;
  height_ = scene_.render.height;
  filename_= scene_.render.filename;
  std::vector<Color> buffer(width_*height_, Color(0.0, 0.0, 0.0));
  colorbuffer_=buffer;
  PpmWriter ppm(width_, height_);
  ppm_ = ppm;

  //Rays für das Bild gernerieren
  std::vector<Ray> rays;
  scene_.cam.generate_rays(width_, height_, rays);
  std::cout << rays.size() << std::endl;

  std::vector<Pixel> pixel;
  for (unsigned i = 0; i < height_; ++i)
  {
    for (unsigned j = 0; j < width_; ++j)
    {
      Pixel p_temp(j,i);
      pixel.push_back(p_temp);
    }
  }

  std::vector<Pixel>::iterator j = pixel.begin();
  //Farbe für jeden Pixel berechnen
  for (std::vector<Ray>::iterator i = rays.begin(); i < rays.end(); ++i)
  {
    Color temp = raytrace(*i);
    (*j).color = temp;
    ++j;
    write(*j);
  }
  ppm_.save(filename_);
}
<commit_msg>Kleines Update bei raytrace, Frage zu lights<commit_after>// -----------------------------------------------------------------------------
// Copyright  : (C) 2014 Andreas-C. Bernstein
// License    : MIT (see the file LICENSE)
// Maintainer : Andreas-C. Bernstein <andreas.bernstein@uni-weimar.de>
// Stability  : experimental
//
// Renderer
// -----------------------------------------------------------------------------

#include "renderer.hpp"
#include "optional_hit.hpp"
#include "ray.hpp"
#include "scene.hpp"
#include "camera.hpp"
#include "sdf_loader.hpp"
#include "color.hpp"
#include "shape.hpp"
#include <algorithm> // min_element

Renderer::Renderer(unsigned w, unsigned h, std::string const& file):
	width_(w),
	height_(h),
	colorbuffer_(w*h, Color(0.0, 0.0, 0.0)),
	filename_(file),
	ppm_(width_, height_)
	{}

Renderer::Renderer():
	width_(0),
	height_(0),
	colorbuffer_(0, Color(0.0, 0.0, 0.0)),
	filename_(""),
	ppm_(width_, height_)
	{}

unsigned Renderer::get_width() const{
  return width_;
}
unsigned Renderer::get_height() const{
  return height_;
}
std::string Renderer::get_filename() const{
  return filename_;
}
Scene Renderer::get_scene() const{
  return scene_;
}

Renderer& Renderer::operator= (Renderer const& rhs){
  width_ = rhs.get_width();
  height_ = rhs.get_height();
  filename_ = rhs.get_filename();
  return *this;
}

void Renderer::render()
{
  const std::size_t checkersize = 20;

  for (unsigned y = 0; y < height_; ++y) {
    for (unsigned x = 0; x < width_; ++x) {
      Pixel p(x,y);
      if ( ((x/checkersize)%2) != ((y/checkersize)%2)) {
        p.color = Color(0.0, 1.0, float(x)/height_);
      } else {
        p.color = Color(1.0, 0.0, float(y)/width_);
      }

      write(p);
    }
  }
  ppm_.save(filename_);
}

void Renderer::write(Pixel const& p)
{
  // flip pixels, because of opengl glDrawPixels
  size_t buf_pos = (width_*p.y + p.x);
  if (buf_pos >= colorbuffer_.size() || (int)buf_pos < 0) {
    std::cerr << "Fatal Error Renderer::write(Pixel p) : "
      << "pixel out of ppm_ : "
      << (int)p.x << "," << (int)p.y
      << std::endl;
  } else {
    colorbuffer_[buf_pos] = p.color;
  }

  ppm_.write(p);
}

Optional_hit Renderer::intersect(Ray const& ray) const{
  Optional_hit o;
  std::vector<float> dis;
  float distance;

  for (std::vector<std::shared_ptr <Shape>>::const_iterator it = scene_.shapes.begin(); it != scene_.shapes.end(); ++it)
  {
    std::shared_ptr <Shape> s_ptr = *it;
    //Shape s = *s_ptr;
    o.hit = s_ptr->intersect_optional(ray, distance, o.intersection, o.normal);
    dis.push_back(distance);
  }

  //suche geringste distance und passendes Shape dazu
  int min_pos = std::distance(dis.begin(), std::min_element(dis.begin(), dis.end()));
  o.shape = &*scene_.shapes[min_pos];
  o.distance = *std::min_element(dis.begin(), dis.end());

  //normal, ... berechnen

  return o;
}

Color Renderer::raytrace(Ray const& ray){
  Optional_hit o = intersect(ray);
  if(o.distance == 0){ //ehemalige depth
    return scene_.ambient;
  }

  if(o.hit) {
    //Light_source l{"licht", {0,0,0}, {1.0,1.0,1.0}, {0.4,0.4,0.4}};
    //Schleife für alle lights?
    Light_source l = scene_.lights[0];
    float tmp = glm::dot(glm::normalize(ray.direction), glm::normalize(l.get_position() - o.intersection)); //intersection ausrechnen lassen bei intersect!
    Material temp_mat = scene_.material[(*o.shape).get_material()];
    float red = temp_mat.get_kd().r * l.get_diffuse().r * tmp;
    float green = temp_mat.get_kd().g * l.get_diffuse().g * tmp;
    float blue = temp_mat.get_kd().b * l.get_diffuse().b * tmp;
    std::cout << tmp << std::endl;
    return Color(red, green, blue);

  }
  else {
    return scene_.ambient;
  }

}

//ungefähres Prozedere? was ist mit den Methoden vom Bernstein?
void Renderer::render_scene(std::string filename){

  //Scene wird geladen
  Sdf_loader loader{filename};
  scene_ = loader.load_scene(filename);

  //Daten aus Transferobejkt in den Renderer schreiben
  width_ = scene_.render.width;
  height_ = scene_.render.height;
  filename_= scene_.render.filename;
  std::vector<Color> buffer(width_*height_, Color(0.0, 0.0, 0.0));
  colorbuffer_=buffer;
  PpmWriter ppm(width_, height_);
  ppm_ = ppm;

  //Rays für das Bild gernerieren
  std::vector<Ray> rays;
  scene_.cam.generate_rays(width_, height_, rays);
  std::cout << rays.size() << std::endl;

  std::vector<Pixel> pixel;
  for (unsigned i = 0; i < height_; ++i)
  {
    for (unsigned j = 0; j < width_; ++j)
    {
      Pixel p_temp(j,i);
      pixel.push_back(p_temp);
    }
  }

  std::vector<Pixel>::iterator j = pixel.begin();
  //Farbe für jeden Pixel berechnen
  for (std::vector<Ray>::iterator i = rays.begin(); i < rays.end(); ++i)
  {
    Color temp = raytrace(*i);
    (*j).color = temp;
    ++j;
    write(*j);
  }
  ppm_.save(filename_);
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    testMetaObject.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <stdio.h>
#include <fstream>
#include <ctype.h>

#include <metaObject.h>
#include <metaUtils.h>
#include "itkNumericTraits.h"

int testMetaObject(int , char *[])
  {
  MetaObject tObj;

  tObj.InitializeEssential(3);
  tObj.FileName("testObject.txt");
  tObj.Comment("TestObject");
  tObj.ObjectTypeName("Object");
  tObj.ObjectSubTypeName("MinorObject");
  tObj.Position(0, 1);
  tObj.Position(1, 2);
  tObj.Position(2, 3);
  float orient[9];
  int i;
  for(i=0; i<9; i++)
    {
    orient[i] = 0;
    }
  orient[0] = 1;
  orient[5] = 1;
  orient[7] = 1;
  tObj.Orientation(orient);
  tObj.ElementSpacing(0, 1);
  tObj.ElementSpacing(1, 2);
  tObj.ElementSpacing(2, 1);

  // Add user's defined fields
  int myarray[3];
  myarray[0]=1;
  myarray[1]=2;
  myarray[2]=3;
  tObj.AddUserField("MyName", MET_STRING, strlen("Julien"), "Julien");
  tObj.AddUserField("MyArray", MET_INT_ARRAY,3,myarray);

  float myMatrix[4];
  for(i=0; i<4; i++)
    {
    myMatrix[i] = i;
    }
  tObj.AddUserField("MyMatrix", MET_FLOAT_MATRIX,2,myMatrix);

  tObj.PrintInfo();
  tObj.Write();

  tObj.Clear();
  tObj.ClearUserFields();

  tObj.AddUserField("MyName", MET_STRING);
  tObj.AddUserField("MyArray", MET_INT_ARRAY,3);
  tObj.AddUserField("MyMatrix", MET_FLOAT_MATRIX,2);

  std::cout << "Test Reading: ";
  tObj.Read();
  std::cout << "[PASSED]" << std::endl;

  tObj.PrintInfo();

  char* name = static_cast<char*>(tObj.GetUserField("MyName"));
  if(strcmp(name,"Julien"))
  {
    std::cout << "MyName: FAIL" << std::endl;
    return 1;
  }

  delete [] name;

  int* array = static_cast<int*>(tObj.GetUserField("MyArray"));

  for(i=0;i<3;i++)
  {
    if(array[i] != i+1)
    {
      std::cout << "MyArray: FAIL" << std::endl;
      return 1;
    }
  }

  delete [] array;

  float* matrix = static_cast<float*>(tObj.GetUserField("MyMatrix"));
  for(i=0; i<4; i++)
    {
    if(matrix[i] != i)
      {
      std::cout << "MyMatrix: FAIL" << std::endl;
      return 1;
      }
    }

  delete [] matrix;

  std::cout << "PASSED!" << std::endl;

  tObj.Clear();
  tObj.ClearUserFields();

  tObj.FileName("testObject2.txt");
  tObj.InitializeEssential(2);
  tObj.Position(0, 4);
  tObj.ElementSpacing(0,2);
  tObj.PrintInfo();
  tObj.Write();
  tObj.Clear();

  tObj.Read();
  tObj.PrintInfo();
  if(tObj.NDims() != 2)
    {
    std::cout << "NDims: FAIL" << std::endl;
    return 1;
    }
  else
    {
    std::cout << "NDims: PASS" << std::endl;
    }

  int zero = 0;
  if(tObj.Position(zero) != 4)
    {
    std::cout << "Position: FAIL :" << tObj.Position(zero) << std::endl;
    return 1;
    }
  else
    {
    std::cout << "Position: PASS" << std::endl;
    }

  if(tObj.ElementSpacing(zero) != 2)
    {
    std::cout << "ElementSpacing: FAIL: " << tObj.ElementSpacing(zero) << std::endl;
    return 1;
    }
  else
    {
    std::cout << "ElementSpacing: PASS" << std::endl;
    }

  // testing metaUtils

  char* inDataChar = new char[1];
  inDataChar[0]=1;
  char* outDataChar = new char[1];
  if(!MET_ValueToValue(MET_CHAR_ARRAY,inDataChar,0,MET_CHAR_ARRAY,outDataChar))
    {
    std::cout << "MET_ValueToValue: FAIL" << std::endl;
    return 1;
    }
  else
    {
    std::cout << "outDataChar = " << static_cast<itk::NumericTraits<char>::PrintType>(outDataChar[0]) << std::endl;
    }

  delete [] inDataChar;
  delete [] outDataChar;

  unsigned char* inDataUChar = new unsigned char[1];
  inDataUChar[0]=1;
  unsigned char* outDataUChar = new unsigned char[1];
  if(!MET_ValueToValue(MET_UCHAR_ARRAY,inDataUChar,0,MET_UCHAR_ARRAY,outDataUChar))
    {
    std::cout << "MET_ValueToValue: FAIL" << std::endl;
    return 1;
    }
  else
    {
    std::cout << "outDataUChar = " << static_cast<itk::NumericTraits<char>::PrintType>(outDataUChar[0]) << std::endl;
    }

  delete [] inDataUChar;
  delete [] outDataUChar;

  std::cout << "[DONE]" << std::endl;
  return 0;
  }

<commit_msg>ENH: Orientation is now of type double<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    testMetaObject.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <stdio.h>
#include <fstream>
#include <ctype.h>

#include <metaObject.h>
#include <metaUtils.h>
#include "itkNumericTraits.h"

int testMetaObject(int , char *[])
  {
  MetaObject tObj;

  tObj.InitializeEssential(3);
  tObj.FileName("testObject.txt");
  tObj.Comment("TestObject");
  tObj.ObjectTypeName("Object");
  tObj.ObjectSubTypeName("MinorObject");
  tObj.Position(0, 1);
  tObj.Position(1, 2);
  tObj.Position(2, 3);
  double orient[9];
  int i;
  for(i=0; i<9; i++)
    {
    orient[i] = 0;
    }
  orient[0] = 1;
  orient[5] = 1;
  orient[7] = 1;
  tObj.Orientation(orient);
  tObj.ElementSpacing(0, 1);
  tObj.ElementSpacing(1, 2);
  tObj.ElementSpacing(2, 1);

  // Add user's defined fields
  int myarray[3];
  myarray[0]=1;
  myarray[1]=2;
  myarray[2]=3;
  tObj.AddUserField("MyName", MET_STRING, strlen("Julien"), "Julien");
  tObj.AddUserField("MyArray", MET_INT_ARRAY,3,myarray);

  float myMatrix[4];
  for(i=0; i<4; i++)
    {
    myMatrix[i] = i;
    }
  tObj.AddUserField("MyMatrix", MET_FLOAT_MATRIX,2,myMatrix);

  tObj.PrintInfo();
  tObj.Write();

  tObj.Clear();
  tObj.ClearUserFields();

  tObj.AddUserField("MyName", MET_STRING);
  tObj.AddUserField("MyArray", MET_INT_ARRAY,3);
  tObj.AddUserField("MyMatrix", MET_FLOAT_MATRIX,2);

  std::cout << "Test Reading: ";
  tObj.Read();
  std::cout << "[PASSED]" << std::endl;

  tObj.PrintInfo();

  char* name = static_cast<char*>(tObj.GetUserField("MyName"));
  if(strcmp(name,"Julien"))
  {
    std::cout << "MyName: FAIL" << std::endl;
    return 1;
  }

  delete [] name;

  int* array = static_cast<int*>(tObj.GetUserField("MyArray"));

  for(i=0;i<3;i++)
  {
    if(array[i] != i+1)
    {
      std::cout << "MyArray: FAIL" << std::endl;
      return 1;
    }
  }

  delete [] array;

  float* matrix = static_cast<float*>(tObj.GetUserField("MyMatrix"));
  for(i=0; i<4; i++)
    {
    if(matrix[i] != i)
      {
      std::cout << "MyMatrix: FAIL" << std::endl;
      return 1;
      }
    }

  delete [] matrix;

  std::cout << "PASSED!" << std::endl;

  tObj.Clear();
  tObj.ClearUserFields();

  tObj.FileName("testObject2.txt");
  tObj.InitializeEssential(2);
  tObj.Position(0, 4);
  tObj.ElementSpacing(0,2);
  tObj.PrintInfo();
  tObj.Write();
  tObj.Clear();

  tObj.Read();
  tObj.PrintInfo();
  if(tObj.NDims() != 2)
    {
    std::cout << "NDims: FAIL" << std::endl;
    return 1;
    }
  else
    {
    std::cout << "NDims: PASS" << std::endl;
    }

  int zero = 0;
  if(tObj.Position(zero) != 4)
    {
    std::cout << "Position: FAIL :" << tObj.Position(zero) << std::endl;
    return 1;
    }
  else
    {
    std::cout << "Position: PASS" << std::endl;
    }

  if(tObj.ElementSpacing(zero) != 2)
    {
    std::cout << "ElementSpacing: FAIL: " << tObj.ElementSpacing(zero) << std::endl;
    return 1;
    }
  else
    {
    std::cout << "ElementSpacing: PASS" << std::endl;
    }

  // testing metaUtils

  char* inDataChar = new char[1];
  inDataChar[0]=1;
  char* outDataChar = new char[1];
  if(!MET_ValueToValue(MET_CHAR_ARRAY,inDataChar,0,MET_CHAR_ARRAY,outDataChar))
    {
    std::cout << "MET_ValueToValue: FAIL" << std::endl;
    return 1;
    }
  else
    {
    std::cout << "outDataChar = " << static_cast<itk::NumericTraits<char>::PrintType>(outDataChar[0]) << std::endl;
    }

  delete [] inDataChar;
  delete [] outDataChar;

  unsigned char* inDataUChar = new unsigned char[1];
  inDataUChar[0]=1;
  unsigned char* outDataUChar = new unsigned char[1];
  if(!MET_ValueToValue(MET_UCHAR_ARRAY,inDataUChar,0,MET_UCHAR_ARRAY,outDataUChar))
    {
    std::cout << "MET_ValueToValue: FAIL" << std::endl;
    return 1;
    }
  else
    {
    std::cout << "outDataUChar = " << static_cast<itk::NumericTraits<char>::PrintType>(outDataUChar[0]) << std::endl;
    }

  delete [] inDataUChar;
  delete [] outDataUChar;

  std::cout << "[DONE]" << std::endl;
  return 0;
  }

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013-2014, Ford Motor Company
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following
 * disclaimer in the documentation and/or other materials provided with the
 * distribution.
 *
 * Neither the name of the Ford Motor Company nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <string>
#include <iostream>
#include "gtest/gtest.h"
#include "connection_handler/heartbeat_monitor.h"
#include "connection_handler/connection.h"
#include "connection_handler/connection_handler.h"
#include "connection_handler/mock_connection_handler.h"
#include "utils/test_async_waiter.h"

namespace {
const int32_t MILLISECONDS_IN_SECOND = 1000;
const int32_t MICROSECONDS_IN_MILLISECONDS = 1000;
const int32_t MICROSECONDS_IN_SECOND = 1000 * 1000;
const uint32_t kTime_offset = 20u;
}

namespace test {
namespace components {
namespace connection_handler_test {

using ::testing::DoAll;
using ::testing::_;
using ::testing::Return;

class HeartBeatMonitorTest : public testing::Test {
 public:
  HeartBeatMonitorTest()
      : connection_(NULL)
      , timeout_(100u)
      , time_allowance_multiplier_(1.5)
      , expiration_timeout_(timeout_ * 2u) {}

 protected:
  testing::NiceMock<MockConnectionHandler> connection_handler_mock_;
  connection_handler::Connection* connection_;
  const uint32_t timeout_;
  const float_t time_allowance_multiplier_;
  const uint32_t expiration_timeout_;
  static const connection_handler::ConnectionHandle connection_handle_ =
      0xABCDEF;
  static const transport_manager::ConnectionUID kDefaultConnectionHandle = 1;
  static const uint32_t kDefaultSessionId = 1;

  void SetUp() OVERRIDE {
    connection_ = new connection_handler::Connection(
        connection_handle_, 0, &connection_handler_mock_, timeout_);
  }

  void TearDown() OVERRIDE {
    delete connection_;
  }
};

ACTION_P2(RemoveSession, conn, session_id) {
  conn->RemoveSession(session_id);
}

TEST_F(HeartBeatMonitorTest, TimerNotStarted) {
  EXPECT_CALL(connection_handler_mock_, AddSession(_))
      .WillOnce(Return(kDefaultSessionId));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kDefaultSessionId))
      .WillOnce(Return(true));  // called by destructor of Connection

  // Whithout StartHeartBeat nothing to be call
  EXPECT_CALL(connection_handler_mock_, CloseSession(_, _)).Times(0);
  EXPECT_CALL(connection_handler_mock_, CloseConnection(_)).Times(0);
  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, _)).Times(0);

  connection_->AddNewSession(kDefaultConnectionHandle);
}

TEST_F(HeartBeatMonitorTest, TimerNotElapsed) {
  EXPECT_CALL(connection_handler_mock_, AddSession(_))
      .WillOnce(Return(kDefaultSessionId));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kDefaultSessionId))
      .WillOnce(Return(true));

  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, _)).Times(0);
  EXPECT_CALL(connection_handler_mock_, CloseSession(_, _)).Times(0);
  EXPECT_CALL(connection_handler_mock_, CloseConnection(_)).Times(0);

  const uint32_t session = connection_->AddNewSession(kDefaultConnectionHandle);
  connection_->StartHeartBeat(session);
}

TEST_F(HeartBeatMonitorTest, TimerElapsed) {
  EXPECT_CALL(connection_handler_mock_, AddSession(_))
      .WillOnce(Return(kDefaultSessionId));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kDefaultSessionId))
      .WillOnce(Return(true));  // invoked by RemoveSession action

  const uint32_t session = connection_->AddNewSession(kDefaultConnectionHandle);

  TestAsyncWaiter waiter;
  uint32_t times = 0;
  EXPECT_CALL(connection_handler_mock_, CloseSession(_, session, _))
      .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter),
                      RemoveSession(connection_, session)));
  times++;
  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, session))
      .WillOnce(NotifyTestAsyncWaiter(&waiter));
  times++;

  connection_->StartHeartBeat(session);

  EXPECT_TRUE(waiter.WaitFor(
      times,
      2 * timeout_ * MICROSECONDS_IN_MILLISECONDS + MICROSECONDS_IN_SECOND));
}

TEST_F(HeartBeatMonitorTest, KeptAlive) {
  EXPECT_CALL(connection_handler_mock_, AddSession(_))
      .WillOnce(Return(kDefaultSessionId));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kDefaultSessionId))
      .WillOnce(Return(true));

  EXPECT_CALL(connection_handler_mock_, CloseSession(_, _)).Times(0);
  EXPECT_CALL(connection_handler_mock_, CloseConnection(_)).Times(0);
  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, _)).Times(0);

  const uint32_t session = connection_->AddNewSession(kDefaultConnectionHandle);
  connection_->StartHeartBeat(session);
  usleep(timeout_);
  connection_->KeepAlive(session);
  usleep(timeout_);
  connection_->KeepAlive(session);
}

TEST_F(HeartBeatMonitorTest, NotKeptAlive) {
  EXPECT_CALL(connection_handler_mock_, AddSession(_))
      .WillOnce(Return(kDefaultSessionId));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kDefaultSessionId))
      .WillOnce(Return(true));

  const uint32_t session = connection_->AddNewSession(kDefaultConnectionHandle);

  TestAsyncWaiter waiter;
  uint32_t times = 0;
  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, session))
      .WillOnce(NotifyTestAsyncWaiter(&waiter));
  times++;
  EXPECT_CALL(connection_handler_mock_, CloseSession(_, session, _))
      .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter),
                      RemoveSession(connection_, session)));
  times++;

  connection_->StartHeartBeat(session);
  usleep(timeout_);
  connection_->KeepAlive(session);

  EXPECT_TRUE(waiter.WaitFor(
      times,
      2 * timeout_ * MICROSECONDS_IN_MILLISECONDS + MICROSECONDS_IN_SECOND));
}

TEST_F(HeartBeatMonitorTest, TwoSessionsElapsed) {
  const uint32_t kMockSessionId1 = 1;
  const uint32_t kMockSessionId2 = 2;
  EXPECT_CALL(connection_handler_mock_, AddSession(_))
      .WillOnce(Return(kMockSessionId1))
      .WillOnce(Return(kMockSessionId2));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kMockSessionId1))
      .WillOnce(Return(true));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kMockSessionId2))
      .WillOnce(Return(true));

  const uint32_t kSession1 = connection_->AddNewSession(kDefaultConnectionHandle);

  const transport_manager::ConnectionUID kAnotherConnectionHandle = 2;
  const uint32_t kSession2 = connection_->AddNewSession(kAnotherConnectionHandle);

  TestAsyncWaiter waiter;
  uint32_t times = 0;
  EXPECT_CALL(connection_handler_mock_, CloseSession(_, kSession1, _))
      .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter),
                      RemoveSession(connection_, kSession1)));
  times++;
  EXPECT_CALL(connection_handler_mock_, CloseSession(_, kSession2, _))
      .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter),
                      RemoveSession(connection_, kSession2)));
  times++;

  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, kSession1))
      .WillOnce(NotifyTestAsyncWaiter(&waiter));
  times++;
  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, kSession2))
      .WillOnce(NotifyTestAsyncWaiter(&waiter));
  times++;

  connection_->StartHeartBeat(kSession1);
  connection_->StartHeartBeat(kSession2);

  EXPECT_TRUE(waiter.WaitFor(
      times,
      2 * timeout_ * MICROSECONDS_IN_MILLISECONDS + MICROSECONDS_IN_SECOND));
}

TEST_F(HeartBeatMonitorTest, IncreaseHeartBeatTimeout) {
  EXPECT_CALL(connection_handler_mock_, AddSession(_))
      .WillOnce(Return(kDefaultSessionId));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kDefaultSessionId))
      .WillOnce(Return(true));

  const uint32_t kSession = connection_->AddNewSession(kDefaultConnectionHandle);

  EXPECT_CALL(connection_handler_mock_, CloseSession(_, _)).Times(0);
  EXPECT_CALL(connection_handler_mock_, CloseConnection(_)).Times(0);
  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, _)).Times(0);

  const uint32_t kNewTimeout = timeout_ + MICROSECONDS_IN_MILLISECONDS;
  connection_->StartHeartBeat(kSession);
  connection_->SetHeartBeatTimeout(kNewTimeout, kSession);
}

TEST_F(HeartBeatMonitorTest, DecreaseHeartBeatTimeout) {
  EXPECT_CALL(connection_handler_mock_, AddSession(_))
      .WillOnce(Return(kDefaultSessionId));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kDefaultSessionId))
      .WillOnce(Return(true));

  const uint32_t kSession = connection_->AddNewSession(kDefaultConnectionHandle);

  TestAsyncWaiter waiter;
  uint32_t times = 0;
  EXPECT_CALL(connection_handler_mock_, CloseSession(_, kSession, _))
      .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter),
                      RemoveSession(connection_, kSession)));
  times++;
  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, kSession))
      .WillOnce(NotifyTestAsyncWaiter(&waiter));
  times++;

  const uint32_t new_timeout = timeout_ - kTime_offset;
  connection_->StartHeartBeat(kSession);
  connection_->SetHeartBeatTimeout(new_timeout, kSession);

  EXPECT_TRUE(waiter.WaitFor(
      times,
      2 * timeout_ * MICROSECONDS_IN_MILLISECONDS + MICROSECONDS_IN_SECOND));
}

}  // namespace connection_handler_test
}  // namespace components
}  // namespace test
<commit_msg>Fix style<commit_after>/*
 * Copyright (c) 2013-2014, Ford Motor Company
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following
 * disclaimer in the documentation and/or other materials provided with the
 * distribution.
 *
 * Neither the name of the Ford Motor Company nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <string>
#include <iostream>
#include "gtest/gtest.h"
#include "connection_handler/heartbeat_monitor.h"
#include "connection_handler/connection.h"
#include "connection_handler/connection_handler.h"
#include "connection_handler/mock_connection_handler.h"
#include "utils/test_async_waiter.h"

namespace {
const int32_t MILLISECONDS_IN_SECOND = 1000;
const int32_t MICROSECONDS_IN_MILLISECONDS = 1000;
const int32_t MICROSECONDS_IN_SECOND = 1000 * 1000;
const uint32_t kTime_offset = 20u;
}

namespace test {
namespace components {
namespace connection_handler_test {

using ::testing::DoAll;
using ::testing::_;
using ::testing::Return;

class HeartBeatMonitorTest : public testing::Test {
 public:
  HeartBeatMonitorTest()
      : connection_(NULL)
      , timeout_(100u)
      , time_allowance_multiplier_(1.5)
      , expiration_timeout_(timeout_ * 2u) {}

 protected:
  testing::NiceMock<MockConnectionHandler> connection_handler_mock_;
  connection_handler::Connection* connection_;
  const uint32_t timeout_;
  const float_t time_allowance_multiplier_;
  const uint32_t expiration_timeout_;
  static const connection_handler::ConnectionHandle connection_handle_ =
      0xABCDEF;
  static const transport_manager::ConnectionUID kDefaultConnectionHandle = 1;
  static const uint32_t kDefaultSessionId = 1;

  void SetUp() OVERRIDE {
    connection_ = new connection_handler::Connection(
        connection_handle_, 0, &connection_handler_mock_, timeout_);
  }

  void TearDown() OVERRIDE {
    delete connection_;
  }
};

ACTION_P2(RemoveSession, conn, session_id) {
  conn->RemoveSession(session_id);
}

TEST_F(HeartBeatMonitorTest, TimerNotStarted) {
  EXPECT_CALL(connection_handler_mock_, AddSession(_))
      .WillOnce(Return(kDefaultSessionId));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kDefaultSessionId))
      .WillOnce(Return(true));  // called by destructor of Connection

  // Whithout StartHeartBeat nothing to be call
  EXPECT_CALL(connection_handler_mock_, CloseSession(_, _)).Times(0);
  EXPECT_CALL(connection_handler_mock_, CloseConnection(_)).Times(0);
  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, _)).Times(0);

  connection_->AddNewSession(kDefaultConnectionHandle);
}

TEST_F(HeartBeatMonitorTest, TimerNotElapsed) {
  EXPECT_CALL(connection_handler_mock_, AddSession(_))
      .WillOnce(Return(kDefaultSessionId));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kDefaultSessionId))
      .WillOnce(Return(true));

  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, _)).Times(0);
  EXPECT_CALL(connection_handler_mock_, CloseSession(_, _)).Times(0);
  EXPECT_CALL(connection_handler_mock_, CloseConnection(_)).Times(0);

  const uint32_t session = connection_->AddNewSession(kDefaultConnectionHandle);
  connection_->StartHeartBeat(session);
}

TEST_F(HeartBeatMonitorTest, TimerElapsed) {
  EXPECT_CALL(connection_handler_mock_, AddSession(_))
      .WillOnce(Return(kDefaultSessionId));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kDefaultSessionId))
      .WillOnce(Return(true));  // invoked by RemoveSession action

  const uint32_t session = connection_->AddNewSession(kDefaultConnectionHandle);

  TestAsyncWaiter waiter;
  uint32_t times = 0;
  EXPECT_CALL(connection_handler_mock_, CloseSession(_, session, _))
      .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter),
                      RemoveSession(connection_, session)));
  times++;
  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, session))
      .WillOnce(NotifyTestAsyncWaiter(&waiter));
  times++;

  connection_->StartHeartBeat(session);

  EXPECT_TRUE(waiter.WaitFor(
      times,
      2 * timeout_ * MICROSECONDS_IN_MILLISECONDS + MICROSECONDS_IN_SECOND));
}

TEST_F(HeartBeatMonitorTest, KeptAlive) {
  EXPECT_CALL(connection_handler_mock_, AddSession(_))
      .WillOnce(Return(kDefaultSessionId));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kDefaultSessionId))
      .WillOnce(Return(true));

  EXPECT_CALL(connection_handler_mock_, CloseSession(_, _)).Times(0);
  EXPECT_CALL(connection_handler_mock_, CloseConnection(_)).Times(0);
  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, _)).Times(0);

  const uint32_t session = connection_->AddNewSession(kDefaultConnectionHandle);
  connection_->StartHeartBeat(session);
  usleep(timeout_);
  connection_->KeepAlive(session);
  usleep(timeout_);
  connection_->KeepAlive(session);
}

TEST_F(HeartBeatMonitorTest, NotKeptAlive) {
  EXPECT_CALL(connection_handler_mock_, AddSession(_))
      .WillOnce(Return(kDefaultSessionId));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kDefaultSessionId))
      .WillOnce(Return(true));

  const uint32_t session = connection_->AddNewSession(kDefaultConnectionHandle);

  TestAsyncWaiter waiter;
  uint32_t times = 0;
  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, session))
      .WillOnce(NotifyTestAsyncWaiter(&waiter));
  times++;
  EXPECT_CALL(connection_handler_mock_, CloseSession(_, session, _))
      .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter),
                      RemoveSession(connection_, session)));
  times++;

  connection_->StartHeartBeat(session);
  usleep(timeout_);
  connection_->KeepAlive(session);

  EXPECT_TRUE(waiter.WaitFor(
      times,
      2 * timeout_ * MICROSECONDS_IN_MILLISECONDS + MICROSECONDS_IN_SECOND));
}

TEST_F(HeartBeatMonitorTest, TwoSessionsElapsed) {
  const uint32_t kMockSessionId1 = 1;
  const uint32_t kMockSessionId2 = 2;
  EXPECT_CALL(connection_handler_mock_, AddSession(_))
      .WillOnce(Return(kMockSessionId1))
      .WillOnce(Return(kMockSessionId2));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kMockSessionId1))
      .WillOnce(Return(true));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kMockSessionId2))
      .WillOnce(Return(true));

  const uint32_t kSession1 =
      connection_->AddNewSession(kDefaultConnectionHandle);

  const transport_manager::ConnectionUID kAnotherConnectionHandle = 2;
  const uint32_t kSession2 =
      connection_->AddNewSession(kAnotherConnectionHandle);

  TestAsyncWaiter waiter;
  uint32_t times = 0;
  EXPECT_CALL(connection_handler_mock_, CloseSession(_, kSession1, _))
      .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter),
                      RemoveSession(connection_, kSession1)));
  times++;
  EXPECT_CALL(connection_handler_mock_, CloseSession(_, kSession2, _))
      .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter),
                      RemoveSession(connection_, kSession2)));
  times++;

  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, kSession1))
      .WillOnce(NotifyTestAsyncWaiter(&waiter));
  times++;
  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, kSession2))
      .WillOnce(NotifyTestAsyncWaiter(&waiter));
  times++;

  connection_->StartHeartBeat(kSession1);
  connection_->StartHeartBeat(kSession2);

  EXPECT_TRUE(waiter.WaitFor(
      times,
      2 * timeout_ * MICROSECONDS_IN_MILLISECONDS + MICROSECONDS_IN_SECOND));
}

TEST_F(HeartBeatMonitorTest, IncreaseHeartBeatTimeout) {
  EXPECT_CALL(connection_handler_mock_, AddSession(_))
      .WillOnce(Return(kDefaultSessionId));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kDefaultSessionId))
      .WillOnce(Return(true));

  const uint32_t kSession =
      connection_->AddNewSession(kDefaultConnectionHandle);

  EXPECT_CALL(connection_handler_mock_, CloseSession(_, _)).Times(0);
  EXPECT_CALL(connection_handler_mock_, CloseConnection(_)).Times(0);
  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, _)).Times(0);

  const uint32_t kNewTimeout = timeout_ + MICROSECONDS_IN_MILLISECONDS;
  connection_->StartHeartBeat(kSession);
  connection_->SetHeartBeatTimeout(kNewTimeout, kSession);
}

TEST_F(HeartBeatMonitorTest, DecreaseHeartBeatTimeout) {
  EXPECT_CALL(connection_handler_mock_, AddSession(_))
      .WillOnce(Return(kDefaultSessionId));
  EXPECT_CALL(connection_handler_mock_, RemoveSession(kDefaultSessionId))
      .WillOnce(Return(true));

  const uint32_t kSession =
      connection_->AddNewSession(kDefaultConnectionHandle);

  TestAsyncWaiter waiter;
  uint32_t times = 0;
  EXPECT_CALL(connection_handler_mock_, CloseSession(_, kSession, _))
      .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter),
                      RemoveSession(connection_, kSession)));
  times++;
  EXPECT_CALL(connection_handler_mock_, SendHeartBeat(_, kSession))
      .WillOnce(NotifyTestAsyncWaiter(&waiter));
  times++;

  const uint32_t new_timeout = timeout_ - kTime_offset;
  connection_->StartHeartBeat(kSession);
  connection_->SetHeartBeatTimeout(new_timeout, kSession);

  EXPECT_TRUE(waiter.WaitFor(
      times,
      2 * timeout_ * MICROSECONDS_IN_MILLISECONDS + MICROSECONDS_IN_SECOND));
}

}  // namespace connection_handler_test
}  // namespace components
}  // namespace test
<|endoftext|>