# Code Excerpt for Texture Model Brick

    Scalar TextureBrick::smoothStep(const Scalar& i, const Scalar& a, const Scalar& b){

        if(a==b) return 0;
        if(i<a) return 0;
        if(b<i) return 1;

        Scalar p = (i-a)/(b-a);
        return (p*p*(3-2*p));
    }

    Scalar TextureBrick::step(const Scalar& i, const Scalar& a){
        return (Scalar)(i >= a);
    }

    void TextureBrick::setupParameter(const std::vector<Scalar> &parameter){

      Scalar mortar = 0.01 + Mortar * 0.06;

      shift = (Shift == 1) ? 0.5 : 0;

      mortar_w_ = mortar;
      mortar_h_ = mortar;

      brick_mortar_w_ = BrickX * 0.5 + mortar;
      brick_mortar_h_ = BrickY * 0.5 + mortar;

      mortar_w_ = (mortar * 0.5)/brick_mortar_w_;
      mortar_h_ = (mortar * 0.5)/brick_mortar_h_;

      step_type_ = step_type;
      shift_noise_ = shift_noise;
      add_noise_ = add_noise;

    }

    Scalar TextureBrick::evaluate(const Scalar &x_norm, const Scalar &y_norm){

      //Implementation based on:
      //Ebert, David S. Texturing & Modeling a Procedural Approach. San Francisco, Calif.: Morgan Kaufmann, 2003.

      Scalar value = 0.0;
      float xx, yy, w, h;

      xx = x_norm / brick_mortar_w_;
      yy = y_norm / brick_mortar_h_;
      y_brick_index_ = floor(yy);

      // shift the brick x position per row
      // check for negative coordinates
      if(y_norm >= 0.0){
        xx+=shift_;
      }

      if (fmod(fabs(yy)*0.5,1) > 0.5) xx += shift_;

      if(shift_noise_ == 1) {
          // a bit of randomness for the position of the bricks per row
          Scalar noise = noiseNormalized(0.1,y_brick_index_,0.2) * 0.3;
          if(shift_<0.5) noise*=0.5;
          xx += noise;
      }

      x_brick_index_ = floor(xx);

      xx -= x_brick_index_;
      yy -= y_brick_index_;

      w = step(mortar_w_,xx) - step(1-mortar_w_,xx);
      h = step(mortar_h_,yy) - step(1-mortar_h_,yy);

      value = w*h;

      Scalar brick_noise = 0.32;
      Scalar mortar_noise = 0.14;

      // on the mortar
      if(value < 1) {
        if(step_type_ == 1) {
          // simulate shadow between the bricks
          xx-=(0.25 * mortar_w_);
          yy-=(0.25 * mortar_h_);

          w = (smoothStep(xx, 0, mortar_w_) - smoothStep(xx,  1-mortar_w_, 1)) ;
          h = (smoothStep(yy, 0, mortar_h_) - smoothStep(yy,  1-mortar_h_, 1)) ;
          value = (1 - w*h) / 1.3;
          value = 0.2 + value *0.7;
        }
        mortar_noise = 0.22;
        brick_noise = 0.15;
      } else {
        value -= 0.4*noiseNormalized(x_brick_index_, y_brick_index_+1000, 0.2);
      }

      if(add_noise_) {
        Scalar brick_noise_size = (1-brick_mortar_w_*brick_mortar_h_);
        value -= brick_noise * turbulence(x_norm * brick_noise_size, y_norm* brick_noise_size, 1.3);

        Scalar mortar_noise_size = 120;
        value += mortar_noise * noiseNormalized(mortar_noise_size*x_norm, mortar_noise_size*y_norm, 0.2);

        value-= 0.01*turbulence(1.5*x_norm, 1.5*y_norm, 15);
      }

      return value;

    }