///+ Prefix linkto basiccode1
//// Lines for set up Psychlops environment
#include <psychlops.h>;
using namespace Psychlops;
///- Prefix linkto basiccode1


///+ Main Routine
//// Psychlops runs at the first line of this function psychlops_main().
void psychlops_main() {

    ///+ 0 Declaration linkto basiccode4_1a
    ////Prepare global parameters
     Canvas window(Canvas::window);
     const int imagenumber = 128; // To prepare the image array, the array number should be "const".
     Psychlops::Image img[128]; //Prepare "Image" class variable to make offscreen movie.
     Psychlops::Rectangle centerrect(10,10);
     int imageHsize = 100;  //Width for offscreeen.
     int imageVsize = 100;  //Height for offscreeen.
    ///- 0 Declaration linkto basiccode4_1a



     ///+ 1 Initialize
     ////Initialize image array
     centerrect.centering();
     double _i, _j, sd, env;//variables to axis conversion and Gaussian SD.
     double sfreq, orientation, contrast, phase, lum;

     ///+ 1.0 setimage linkto basiccode4_2b
     ////allocate offscreen images on the main memory in advance
     for (int k=0; k<imagenumber; k++){
         img[k].set(imageHsize, imageVsize); //Allocate offscreen in main memory.
     }
     ///- 1.0 setimage linkto basiccode4_2b

         ///+ 1.1 set1
         for(int i=0; i <imageHsize; i++){
             for(int j=0; j < imageVsize; j++){

            _i = i-imageHsize*0.5; //get position in
            _j = j-imageVsize*0.5; //get position in

            ///+ 1.1.1 gaussian link to basiccode4_1b
            ////Calcurate gaussian envelop
            sd = imageVsize/4.0/*ID:sigma 3.0 8.0 1.0*/; //calculate SD for gaussian
            env=exp(-(_i*_i+_j*_j)/(2.0*(sd*sd)) ); //calculate 2D gaussian
            ///- 1.1.1 gaussian link to basiccode4_1b

              for (int k=0; k<imagenumber; k++){
               ///+ 1.1.2 sin grating
                  ////Carrier moving sinusoidal grating
                  orientation = 30.0/*ID:ori 0.0 180.0 30.0*/ * PI / 180.0; //Orientation
                  contrast = 1.0/*ID:con 0.0 1.0 0.2*/; //Contrast
                  phase = (double)k * 5.0/*ID:speed 0.0 10.0 2.0*/*(2.0/128.0) * PI ; //Phase. To repeat movie, displacement is set as a n times of 2PI/imagenumber.
                  sfreq = 1.0/30.0;
                  lum = contrast * sin(2*PI*sfreq*(_i*sin(orientation)+_j*cos(orientation))+phase); //Sin wave calcuration. y=Lmean+Lmean*contrast*sin(2*PI*f*x+phase);
                  ///- 1.1.2 sin grating
                  img[k].pix(i,j, Color( Color(0.5*(1+lum*env))));
                  }
            }
         }
         ///- 1.1 set1

         ///+ 1.2 locateimage linkto basiccode4_2b
         for (int k=0; k<imagenumber; k++){
            img[k].cache(); //Move offscreen from main memory to video RAM. (Optional)
            img[k].centering().shift(100,100);//set the position to copy offscreen
        }
         ///- 1.2 locateimage linkto basiccode4_2b

    ///- 1 Initialize

    ///+ 2 drawing
    ////copy offscreen onto main frame buffer
    int frame=0;
    while(!Keyboard::esc.pushed()){
        frame++;
        frame = frame % imagenumber; //A frame count should not exceed the frame number of offscreen movies
        window.clear(Color::black); //Clear screen with black
        img[frame].draw(); // copy offscreen onto the reverse side of window buffer.
        centerrect.draw(Color::red);// draw reference rectangle at the center.
        window.flip();
    }
    ///- 2 drawing

}
///- Main Routine

./4_2c.xap