<commit_before>#include "libtg.hpp"

using namespace std;

// argv[0]
string exe;

void usage() {
  cerr << "Usage mode: " << exe << " [options...] \n";
  cerr << endl;
  cerr << "I/O options:\n";
  cerr << "\t-i\t<file path>\tRead formula from file.\n";
  cerr << "\t-oinfo\t<file path>\tAppend formula information to file.\n";
  cerr << "\t-ocnf\t<file path>\tWrite CNF to file.\n";
  cerr << "\t-oproof\t<file path>\tWrite proof formula to file.\n";
  cerr << endl;
  cerr << "Pipeline options:\n";
  cerr << "\t-f\tFlat ((p|(q|r)|s) ---> (p|q|r|s)). Before DAG.\n";
  cerr << "\t-m\tMinimize DAG edges ((p&q)|(p&r&q) ---> (p&q)|((p&q)&r)).\n";
  cerr << "\t-a\t<algorithm number>\tSelect renaming algorithm.\n";
  cerr << "\t-s\tSimplify CNF. (see note 1)\n";
  cerr << "\t-ionly\tOnly compute formula information.\n";
  cerr << endl;
  cerr << "Additional options:\n";
  cerr << "\t-h\tDisplay usage mode.\n";
  cerr << "\t-syntax\tDisplay formula syntax.\n";
  cerr << endl;
  cerr << "Renaming algorithms (see note 2):\n";
  cerr << "\t1\tKnapsack 0-1 based algorithm.\n";
  cerr << "\t2\tBoy de la Tour's algorithm.\n";
  cerr << endl;
  cerr << "Notes:\n";
  cerr << "\t1) CNF simplification removes tautologies, repeated literals\n";
  cerr << "\tand repeated clauses.\n";
  cerr << "\t2) If option -a is not set or an invalid algorithm is passed,\n";
  cerr << "\tthen no renaming will happen at all.\n";
  cerr << "\t3) Formula information format:\n";
  cerr << "\t<file path>,<size>,<number of clauses>,<number of symbols>,\n";
  cerr << endl;
  exit(-1);
}

void syntax() {
  cerr << exe << ": Formula syntax.\n";
  cerr << endl;
  cerr << "Propositional symbols are strings of one or more of the following\n";
  cerr << "ASCII characters:\n";
  cerr << "\t_\t(underscore)\n";
  cerr << "\t0 to 9\t(decimal digits)\n";
  cerr << "\ta to z\t(lowercase letters)\n";
  cerr << "\tA to Z\t(uppercase letters)\n";
  cerr << endl;
  cerr << "Logic connectives are the following strings of ASCII characters:\n";
  cerr << "\t~\t(tilde)\t\t\t\t\t\tNegation.\n";
  cerr << "\t&\t(ampersand)\t\t\t\t\tConjunction.\n";
  cerr << "\t|\t(pipe)\t\t\t\t\t\tDisjunction.\n";
  cerr << "\t=>\t(equals and greater than signs)\t\t\tImplication.\n";
  cerr << "\t<=>\t(less than, equals and greater than signs)\tEquivalence.\n";
  cerr << endl;
  cerr << "Notes:\n";
  cerr << "\t1) Only one line is read by the parser.\n";
  cerr << "\t2) Whitespaces and multiple parentheses are completely ignored.\n";
  cerr << "\tExample:\n";
  cerr << "\t\t(((p => q)))\tis the same as\t\tp=>q\n";
  cerr << endl;
  exit(-1);
}

class Args {
  private:
    int argc;
    char** argv;
    unordered_map<string,int> idx;
  public:
    void init(int argc, char** argv) {
      this->argc = argc;
      this->argv = argv;
      for (int i = argc-1; 1 <= i; i--) idx[argv[i]] = i;
    }
    bool find(const string& str) const {
      return idx.find(str) != idx.end();
    }
    template <typename T>
    T opt(const string& name) const {
      auto it = idx.find(name);
      if (it == idx.end()) usage();
      int i = it->second+1;
      if (argc <= i) usage();
      stringstream ss;
      ss << argv[i];
      T ret;
      ss >> ret;
      if (ss.fail()) usage();
      return ret;
    }
    void checkflag(const string& name) const {
      if (!find(name)) usage();
    }
    template <typename T>
    void checkopt(const string& name, bool required = false) const {
      if (find(name)) opt<T>(name);
      else if (required) usage();
    }
} args;

// files
unordered_map<string,fstream*> files;
ostream& get_output_stream(const string& name, bool append = false) {
  if (!args.find("-o"+name)) return cout;
  string fn = args.opt<string>("-o"+name);
  auto it = files.find(fn);
  if (it != files.end()) return (ostream&)*it->second;
  fstream::openmode md = fstream::out;
  if (append) md = md | fstream::app;
  fstream* file = new fstream(fn,md);
  if (!file->is_open()) {
    cerr << exe << ": ";
    cerr << "error opening `" << fn << "' for " << name << " output.\n";
    exit(-1);
  }
  files[fn] = file;
  return (ostream&)*file;
}
void close_files() {
  for (auto& kv : files) {
    kv.second->close();
    delete kv.second;
  }
}

int main(int argc, char** argv) {
  // init args
  exe = argv[0];
  args.init(argc,argv);

  // display help
  if (args.find("-h")) usage();
  if (args.find("-syntax")) syntax();

  // init input stream
  string in_fn = "stdin";
  if (args.find("-i")) {
    in_fn = args.opt<string>("-i");
    if (!freopen(in_fn.c_str(),"r",stdin)) {
      cerr << exe << ": `" << in_fn << "' not found.\n";
      return -1;
    }
    reverse(in_fn.begin(),in_fn.end());
    auto pos = in_fn.find("/");
    if (pos != string::npos) in_fn = in_fn.substr(0,pos);
    reverse(in_fn.begin(),in_fn.end());
  }

  // init output streams
  ostream& info_stream  = get_output_stream("info", true);
  ostream& cnf_stream   = get_output_stream("cnf");
  ostream& proof_stream = get_output_stream("proof");

  // additional argument checks
  args.checkopt<int>("-a");

  // input
  getline(cin,raw);
  parse();
  stringstream ss;
  ss << T;
  string original = ss.str();

  // info only
  if (args.find("-ionly")) {
    info_stream << in_fn << ",";
    info_stream << size(T) << ",";
    info_stream << clauses(T) << ",";
    info_stream << symbols(T) << ",\n";
    cnf_stream << original << endl;
    close_files();
    return 0;
  }

  // pipeline
  nnf();
  if (args.find("-f")) flat();
  dag();
  if (args.find("-m")) mindag();
  if (args.find("-a")) switch (args.opt<int>("-a")) {
    case 1: knapsack();     break;
    case 2: boydelatour();  break;
  }
  rename();
  if (args.find("-s")) simplecnf();
  else cnf();

  // output
  info_stream << in_fn << ",";
  info_stream << CNF.size() << ",";
  info_stream << CNF.clauses() << ",";
  info_stream << CNF.symbols() << ",\n";
  cnf_stream << CNF << endl;
  proof_stream << "-((" << original << ") <-> (" << CNF << "))\n";

  close_files();

  return 0;
}
<commit_msg>Adapting output<commit_after>#include "libtg.hpp"

using namespace std;

// argv[0]
string exe;

void usage() {
  cerr << "Usage mode: " << exe << " [options...] \n";
  cerr << endl;
  cerr << "I/O options:\n";
  cerr << "\t-i\t<file path>\tRead formula from file.\n";
  cerr << "\t-oinfo\t<file path>\tAppend formula information to file.\n";
  cerr << "\t-ocnf\t<file path>\tWrite CNF to file.\n";
  cerr << "\t-oproof\t<file path>\tWrite proof formula to file.\n";
  cerr << endl;
  cerr << "Pipeline options:\n";
  cerr << "\t-f\tFlat ((p|(q|r)|s) ---> (p|q|r|s)). Before DAG.\n";
  cerr << "\t-m\tMinimize DAG edges ((p&q)|(p&r&q) ---> (p&q)|((p&q)&r)).\n";
  cerr << "\t-a\t<algorithm number>\tSelect renaming algorithm.\n";
  cerr << "\t-s\tSimplify CNF. (see note 1)\n";
  cerr << "\t-ionly\tOnly compute formula information.\n";
  cerr << endl;
  cerr << "Additional options:\n";
  cerr << "\t-h\tDisplay usage mode.\n";
  cerr << "\t-syntax\tDisplay formula syntax.\n";
  cerr << endl;
  cerr << "Renaming algorithms (see note 2):\n";
  cerr << "\t1\tKnapsack 0-1 based algorithm.\n";
  cerr << "\t2\tBoy de la Tour's algorithm.\n";
  cerr << endl;
  cerr << "Notes:\n";
  cerr << "\t1) CNF simplification removes tautologies, repeated literals\n";
  cerr << "\tand repeated clauses.\n";
  cerr << "\t2) If option -a is not set or an invalid algorithm is passed,\n";
  cerr << "\tthen no renaming will happen at all.\n";
  cerr << "\t3) Formula information format:\n";
  cerr << "\t<file path>,<size>,<number of clauses>,<number of symbols>,\n";
  cerr << endl;
  exit(-1);
}

void syntax() {
  cerr << exe << ": Formula syntax.\n";
  cerr << endl;
  cerr << "Propositional symbols are strings of one or more of the following\n";
  cerr << "ASCII characters:\n";
  cerr << "\t_\t(underscore)\n";
  cerr << "\t0 to 9\t(decimal digits)\n";
  cerr << "\ta to z\t(lowercase letters)\n";
  cerr << "\tA to Z\t(uppercase letters)\n";
  cerr << endl;
  cerr << "Logic connectives are the following strings of ASCII characters:\n";
  cerr << "\t~\t(tilde)\t\t\t\t\t\tNegation.\n";
  cerr << "\t&\t(ampersand)\t\t\t\t\tConjunction.\n";
  cerr << "\t|\t(pipe)\t\t\t\t\t\tDisjunction.\n";
  cerr << "\t=>\t(equals and greater than signs)\t\t\tImplication.\n";
  cerr << "\t<=>\t(less than, equals and greater than signs)\tEquivalence.\n";
  cerr << endl;
  cerr << "Notes:\n";
  cerr << "\t1) Only one line is read by the parser.\n";
  cerr << "\t2) Whitespaces and multiple parentheses are completely ignored.\n";
  cerr << "\tExample:\n";
  cerr << "\t\t(((p => q)))\tis the same as\t\tp=>q\n";
  cerr << endl;
  exit(-1);
}

class Args {
  private:
    int argc;
    char** argv;
    unordered_map<string,int> idx;
  public:
    void init(int argc, char** argv) {
      this->argc = argc;
      this->argv = argv;
      for (int i = argc-1; 1 <= i; i--) idx[argv[i]] = i;
    }
    bool find(const string& str) const {
      return idx.find(str) != idx.end();
    }
    template <typename T>
    T opt(const string& name) const {
      auto it = idx.find(name);
      if (it == idx.end()) usage();
      int i = it->second+1;
      if (argc <= i) usage();
      stringstream ss;
      ss << argv[i];
      T ret;
      ss >> ret;
      if (ss.fail()) usage();
      return ret;
    }
    void checkflag(const string& name) const {
      if (!find(name)) usage();
    }
    template <typename T>
    void checkopt(const string& name, bool required = false) const {
      if (find(name)) opt<T>(name);
      else if (required) usage();
    }
} args;

// files
unordered_map<string,fstream*> files;
ostream& get_output_stream(const string& name, bool append = false) {
  if (!args.find("-o"+name)) return cout;
  string fn = args.opt<string>("-o"+name);
  auto it = files.find(fn);
  if (it != files.end()) return (ostream&)*it->second;
  fstream::openmode md = fstream::out;
  if (append) md = md | fstream::app;
  fstream* file = new fstream(fn,md);
  if (!file->is_open()) {
    cerr << exe << ": ";
    cerr << "error opening `" << fn << "' for " << name << " output.\n";
    exit(-1);
  }
  files[fn] = file;
  return (ostream&)*file;
}
void close_files() {
  for (auto& kv : files) {
    kv.second->close();
    delete kv.second;
  }
}

int main(int argc, char** argv) {
  // init args
  exe = argv[0];
  args.init(argc,argv);

  // display help
  if (args.find("-h")) usage();
  if (args.find("-syntax")) syntax();

  // init input stream
  string in_fn = "stdin";
  if (args.find("-i")) {
    in_fn = args.opt<string>("-i");
    if (!freopen(in_fn.c_str(),"r",stdin)) {
      cerr << exe << ": `" << in_fn << "' not found.\n";
      return -1;
    }
    reverse(in_fn.begin(),in_fn.end());
    auto pos = in_fn.find("/");
    if (pos != string::npos) in_fn = in_fn.substr(0,pos);
    reverse(in_fn.begin(),in_fn.end());
  }

  // init output streams
  ostream& info_stream  = get_output_stream("info", true);
  ostream& cnf_stream   = get_output_stream("cnf");
  ostream& proof_stream = get_output_stream("proof");

  // additional argument checks
  args.checkopt<int>("-a");

  // input
  getline(cin,raw);
  parse();
  stringstream ss;
  ss << T;
  string original = ss.str();

  // info only
  if (args.find("-ionly")) {
    info_stream << in_fn << ",";
    info_stream << size(T) << ",";
    info_stream << clauses(T) << ",";
    info_stream << symbols(T) << ",\n";
    cnf_stream << original << endl;
    close_files();
    return 0;
  }

  // pipeline
  nnf();
  if (args.find("-f")) flat();
  dag();
  if (args.find("-m")) mindag();
  if (args.find("-a")) switch (args.opt<int>("-a")) {
    case 1: knapsack();     break;
    case 2: boydelatour();  break;
  }
  rename();
  if (args.find("-s")) simplecnf();
  else cnf();

  // output
  info_stream << in_fn << ",";
  info_stream << CNF.size() << ",";
  info_stream << CNF.clauses() << ",";
  info_stream << CNF.symbols() << ",\n";
  cnf_stream << CNF << endl;
  proof_stream << "formulas(sos).\n";
  proof_stream << "  -((" << original << ") <-> (" << CNF << "))\n";
  proof_stream << "end_of_list.\n";

  close_files();

  return 0;
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2014, Patricio Gonzalez Vivo
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 copyright holder 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 <sys/shm.h>
#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>
#include <map>

#include "app.h"
#include "utils.h"
#include "gl/shader.h"
#include "gl/vbo.h"
#include "gl/texture.h"
#include "3d/camera.h"
#include "types/shapes.h"

#include "ui/cursor.h"

// GLOBAL VARIABLES
//============================================================================
//
static bool bPlay = true;

//  List of FILES to watch and the variable to communicate that between process
struct WatchFile {
    std::string type;
    std::string path;
    int lastChange;
};
std::vector<WatchFile> files;
int* iHasChanged;

//  SHADER
Shader shader;
int iFrag = -1;
std::string fragSource = "";
int iVert = -1;
std::string vertSource = "";

//  CAMERA
Camera cam;
float lat = 180.0;
float lon = 0.0;

//  ASSETS
Vbo* vbo;
int iGeom = -1;
glm::mat4 model_matrix = glm::mat4(1.);

std::map<std::string,Texture*> textures;
std::string outputFile = "";

//  CURSOR
Cursor cursor;
bool bCursor = false;

//  Time limit
float timeLimit = 0.0f;

//================================================================= Functions
void watchThread();
void onFileChange();

void renderThread(int argc, char **argv);
void setup();
void draw();
void onExit();

// Main program
//============================================================================
int main(int argc, char **argv){

    // Load files to watch
    struct stat st;
    for (uint i = 1; i < argc ; i++){
        std::string argument = std::string(argv[i]);

        if ( iFrag == -1 && ( haveExt(argument,"frag") || haveExt(argument,"fs") ) ) {
            int ierr = stat(argument.c_str(), &st);
            if (ierr != 0) {
                    std::cerr << "Error watching file " << argv[i] << std::endl;
            } else {
                WatchFile file;
                file.type = "fragment";
                file.path = argument;
                file.lastChange = st.st_mtime;
                files.push_back(file);
                iFrag = files.size()-1;
            }
        } else if ( iVert == -1 && ( haveExt(argument,"vert") || haveExt(argument,"vs") ) ) {
            int ierr = stat(argument.c_str(), &st);
            if (ierr != 0) {
                    std::cerr << "Error watching file " << argument << std::endl;
            } else {
                WatchFile file;
                file.type = "vertex";
                file.path = argument;
                file.lastChange = st.st_mtime;
                files.push_back(file);
                iVert = files.size()-1;
            }
        } else if ( iGeom == -1 &&
                    ( haveExt(argument,"ply") || haveExt(argument,"PLY") ||
                      haveExt(argument,"obj") || haveExt(argument,"OBJ") ) ) {
            int ierr = stat(argument.c_str(), &st);
            if (ierr != 0) {
                    std::cerr << "Error watching file " << argument << std::endl;
            } else {
                WatchFile file;
                file.type = "geometry";
                file.path = argument;
                file.lastChange = st.st_mtime;
                files.push_back(file);
                iGeom = files.size()-1;
            }
        } else if ( haveExt(argument,"png") || haveExt(argument,"PNG") ||
                    haveExt(argument,"jpg") || haveExt(argument,"JPG") ||
                    haveExt(argument,"jpeg") || haveExt(argument,"JPEG") ){
            int ierr = stat(argument.c_str(), &st);
            if (ierr != 0) {
                    // std::cerr << "Error watching file " << argument << std::endl;
            } else {
                WatchFile file;
                file.type = "image";
                file.path = argument;
                file.lastChange = st.st_mtime;
                files.push_back(file);
            }
        }
    }

    // If no shader
    if( iFrag == -1 && iVert == -1 && iGeom == -1) {
        std::cerr << "Usage: " << argv[0] << " shader.frag [shader.vert] [mesh.(obj/.ply)] [texture.(png/jpg)] [-textureNameA texture.(png/jpg)] [-u] [-x x] [-y y] [-w width] [-h height] [-l/--livecoding] [--square] [-s seconds] [-o screenshot.png]\n";
        return EXIT_FAILURE;
    }

    // Fork process with a shared variable
    //
    int shmId = shmget(IPC_PRIVATE, sizeof(bool), 0666);
    pid_t pid = fork();
    iHasChanged = (int *) shmat(shmId, NULL, 0);

    switch(pid) {
        case -1: //error
        break;

        case 0: // child
        {
            *iHasChanged = -1;
            watchThread();
        }
        break;

        default:
        {
            // Initialize openGL context
            initGL(argc,argv);

            // OpenGL Render Loop
            renderThread(argc,argv);

            //  Kill the iNotify watcher once you finish
            kill(pid, SIGKILL);
            onExit();
        }
        break;
    }

    shmctl(shmId, IPC_RMID, NULL);
    return 0;
}

//  Watching Thread
//============================================================================
void watchThread() {
    struct stat st;
    while(1){
        for(uint i = 0; i < files.size(); i++){
            if( *iHasChanged == -1 ){
                stat(files[i].path.c_str(), &st);
                int date = st.st_mtime;
                if (date != files[i].lastChange ){
                    *iHasChanged = i;
                    files[i].lastChange = date;
                }
                usleep(500000);
            }
        }
    }
}

void renderThread(int argc, char **argv) {
    // Prepare viewport
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT );

    // Setup
    setup();

    // Turn on Alpha blending
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

    // Clear the background
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    int textureCounter = 0;

    //Load the the resources (textures)
    for (uint i = 1; i < argc ; i++){
        std::string argument = std::string(argv[i]);

        if (argument == "-x" || argument == "-y" ||
            argument == "-w" || argument == "--width" ||
            argument == "-h" || argument == "--height" ) {
            i++;
        } else if ( argument == "--square" ||
                    argument == "-l" ||
                    argument == "--life-coding"  ) {

        } else if ( argument == "-m" ) {
            bCursor = true;
            cursor.init();
        } else if ( argument == "-s" || argument == "--sec") {
            i++;
            argument = std::string(argv[i]);
            timeLimit = getFloat(argument);
            std::cout << "Will exit in " << timeLimit << " seconds." << std::endl;
        } else if ( argument == "-o" ){
            i++;
            argument = std::string(argv[i]);
            if( haveExt(argument,"png") ){
                outputFile = argument;
                std::cout << "Will save screenshot to " << outputFile  << " on exit." << std::endl;
            } else {
                std::cout << "At the moment screenshots only support PNG formats" << std::endl;
            }

        } else if (argument.find("-") == 0) {
            std::string parameterPair = argument.substr(argument.find_last_of('-')+1);

            i++;
            argument = std::string(argv[i]);
            Texture* tex = new Texture();
            if( tex->load(argument) ){
                textures[parameterPair] = tex;
                std::cout << "Loading " << argument << " as the following uniform: " << std::endl;
                std::cout << "    uniform sampler2D u_" << parameterPair  << "; // loaded"<< std::endl;
                std::cout << "    uniform vec2 u_" << parameterPair  << "Resolution;"<< std::endl;
            }

        } else if ( haveExt(argument,"png") || haveExt(argument,"PNG") ||
                    haveExt(argument,"jpg") || haveExt(argument,"JPG") ||
                    haveExt(argument,"jpeg") || haveExt(argument,"JPEG") ) {

            Texture* tex = new Texture();
            if( tex->load(argument) ){
                std::string name = "u_tex"+getString(textureCounter);
                textures[name] = tex;
                std::cout << "Loading " << argument << " as the following uniform: " << std::endl;
                std::cout << "    uniform sampler2D " << name  << "; // loaded"<< std::endl;
                std::cout << "    uniform vec2 " << name  << "Resolution;"<< std::endl;
                textureCounter++;
            }
        }
    }

    // Render Loop
    while (isGL() && bPlay) {
        // Update
        updateGL();

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Draw
        draw();

        // Swap the buffers
        renderGL();

        if ( timeLimit > 0.0 && getTime() > timeLimit ) {
            onKeyPress('s');
            bPlay = false;
        }
    }
}

void setup() {
    glEnable(GL_DEPTH_TEST);
    glFrontFace(GL_CCW);

    //  Load Geometry
    //
    if ( iGeom == -1 ){
        vbo = rect(0.0,0.0,1.0,1.0).getVbo();
    } else {
        Mesh model;
        model.load(files[iGeom].path);
        vbo = model.getVbo();
        glm::vec3 toCentroid = getCentroid(model.getVertices());
        // model_matrix = glm::scale(glm::vec3(0.001));
        model_matrix = glm::translate(-toCentroid);
    }

    //  Build shader;
    //
    if ( iFrag != -1 ) {
        fragSource = "";
        if(!loadFromPath(files[iFrag].path, &fragSource)) {
            return;
        }
    } else {
        fragSource = vbo->getVertexLayout()->getDefaultFragShader();
    }

    if ( iVert != -1 ) {
        vertSource = "";
        loadFromPath(files[iVert].path, &vertSource);
    } else {
        vertSource = vbo->getVertexLayout()->getDefaultVertShader();
    }
    shader.load(fragSource,vertSource);

    cam.setViewport(getWindowWidth(),getWindowHeight());
    cam.setPosition(glm::vec3(0.0,0.0,-3.));
}

void draw(){

    // Something change??
    if(*iHasChanged != -1) {
        onFileChange();
        *iHasChanged = -1;
    }

    shader.use();
    shader.setUniform("u_time", getTime());
    shader.setUniform("u_mouse", getMouseX(), getMouseY());
    shader.setUniform("u_resolution",getWindowWidth(), getWindowHeight());

    glm::mat4 mvp = glm::mat4(1.);
    if (iGeom != -1) {
        shader.setUniform("u_eye", -cam.getPosition());
        shader.setUniform("u_normalMatrix", cam.getNormalMatrix());

        shader.setUniform("u_modelMatrix", model_matrix);
        shader.setUniform("u_viewMatrix", cam.getViewMatrix());
        shader.setUniform("u_projectionMatrix", cam.getProjectionMatrix());

        mvp = cam.getProjectionViewMatrix() * model_matrix;
    }
    shader.setUniform("u_modelViewProjectionMatrix", mvp);

    unsigned int index = 0;
    for (std::map<std::string,Texture*>::iterator it = textures.begin(); it!=textures.end(); ++it) {
        shader.setUniform(it->first,it->second,index);
        shader.setUniform(it->first+"Resolution",it->second->getWidth(),it->second->getHeight());
        index++;
    }

    vbo->draw(&shader);

    if(bCursor){
        cursor.draw();
    }
}

// Rendering Thread
//============================================================================
void onFileChange(){
    std::string type = files[*iHasChanged].type;
    std::string path = files[*iHasChanged].path;

    if ( type == "fragment" ){
        fragSource = "";
        if(loadFromPath(path, &fragSource)){
            shader.detach(GL_FRAGMENT_SHADER | GL_VERTEX_SHADER);
            shader.load(fragSource,vertSource);
        }
    } else if ( type == "vertex" ){
        vertSource = "";
        if(loadFromPath(path, &vertSource)){
            shader.detach(GL_FRAGMENT_SHADER | GL_VERTEX_SHADER);
            shader.load(fragSource,vertSource);
        }
    } else if ( type == "geometry" ){
        // TODO
    } else if ( type == "image" ){
        for (std::map<std::string,Texture*>::iterator it = textures.begin(); it!=textures.end(); ++it) {
            if ( path == it->second->getFilePath() ){
                it->second->load(path);
                break;
            }
        }
    }
}

void onKeyPress(int _key) {
    if( _key == 'q' || _key == 'Q' || _key == 's' || _key == 'S' ){
        if (outputFile != "") {
            unsigned char* pixels = new unsigned char[getWindowWidth()*getWindowHeight()*4];
            glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE, pixels);
            Texture::savePixels(outputFile, pixels, getWindowWidth(), getWindowHeight());
        }
    }

    if ( _key == 'q' || _key == 'Q'){
        bPlay = false;
    }
}

void onMouseMove(float _x, float _y) {

}

void onMouseClick(float _x, float _y, int _button) {

}

void onMouseDrag(float _x, float _y, int _button) {
    if (_button == 1){
        float dist = glm::length(cam.getPosition());
        lat -= getMouseVelX();
        lon -= getMouseVelY()*0.5;
        cam.orbit(lat,lon,dist);
        cam.lookAt(glm::vec3(0.0));
    } else {
        float dist = glm::length(cam.getPosition());
        dist += (-.008f * getMouseVelY());
        if(dist > 0.0f){
            cam.setPosition( -dist * cam.getZAxis() );
            cam.lookAt(glm::vec3(0.0));
        }
    }
}

void onViewportResize(int _newWidth, int _newHeight) {
    cam.setViewport(_newWidth,_newHeight);
}

void onExit() {
    // clear screen
    glClear( GL_COLOR_BUFFER_BIT );

    // close openGL instance
    closeGL();

    // DELETE RESOURCES
    for (std::map<std::string,Texture*>::iterator i = textures.begin(); i != textures.end(); ++i) {
        delete i->second;
        i->second = NULL;
    }
    textures.clear();
    delete vbo;
}<commit_msg>fixing console out<commit_after>/*
Copyright (c) 2014, Patricio Gonzalez Vivo
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 copyright holder 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 <sys/shm.h>
#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>
#include <map>

#include "app.h"
#include "utils.h"
#include "gl/shader.h"
#include "gl/vbo.h"
#include "gl/texture.h"
#include "3d/camera.h"
#include "types/shapes.h"

#include "ui/cursor.h"

// GLOBAL VARIABLES
//============================================================================
//
static bool bPlay = true;

//  List of FILES to watch and the variable to communicate that between process
struct WatchFile {
    std::string type;
    std::string path;
    int lastChange;
};
std::vector<WatchFile> files;
int* iHasChanged;

//  SHADER
Shader shader;
int iFrag = -1;
std::string fragSource = "";
int iVert = -1;
std::string vertSource = "";

//  CAMERA
Camera cam;
float lat = 180.0;
float lon = 0.0;

//  ASSETS
Vbo* vbo;
int iGeom = -1;
glm::mat4 model_matrix = glm::mat4(1.);

std::map<std::string,Texture*> textures;
std::string outputFile = "";

//  CURSOR
Cursor cursor;
bool bCursor = false;

//  Time limit
float timeLimit = 0.0f;

//================================================================= Functions
void watchThread();
void onFileChange();

void renderThread(int argc, char **argv);
void setup();
void draw();
void onExit();

// Main program
//============================================================================
int main(int argc, char **argv){

    // Load files to watch
    struct stat st;
    for (uint i = 1; i < argc ; i++){
        std::string argument = std::string(argv[i]);

        if ( iFrag == -1 && ( haveExt(argument,"frag") || haveExt(argument,"fs") ) ) {
            int ierr = stat(argument.c_str(), &st);
            if (ierr != 0) {
                    std::cerr << "Error watching file " << argv[i] << std::endl;
            } else {
                WatchFile file;
                file.type = "fragment";
                file.path = argument;
                file.lastChange = st.st_mtime;
                files.push_back(file);
                iFrag = files.size()-1;
            }
        } else if ( iVert == -1 && ( haveExt(argument,"vert") || haveExt(argument,"vs") ) ) {
            int ierr = stat(argument.c_str(), &st);
            if (ierr != 0) {
                    std::cerr << "Error watching file " << argument << std::endl;
            } else {
                WatchFile file;
                file.type = "vertex";
                file.path = argument;
                file.lastChange = st.st_mtime;
                files.push_back(file);
                iVert = files.size()-1;
            }
        } else if ( iGeom == -1 &&
                    ( haveExt(argument,"ply") || haveExt(argument,"PLY") ||
                      haveExt(argument,"obj") || haveExt(argument,"OBJ") ) ) {
            int ierr = stat(argument.c_str(), &st);
            if (ierr != 0) {
                    std::cerr << "Error watching file " << argument << std::endl;
            } else {
                WatchFile file;
                file.type = "geometry";
                file.path = argument;
                file.lastChange = st.st_mtime;
                files.push_back(file);
                iGeom = files.size()-1;
            }
        } else if ( haveExt(argument,"png") || haveExt(argument,"PNG") ||
                    haveExt(argument,"jpg") || haveExt(argument,"JPG") ||
                    haveExt(argument,"jpeg") || haveExt(argument,"JPEG") ){
            int ierr = stat(argument.c_str(), &st);
            if (ierr != 0) {
                    // std::cerr << "Error watching file " << argument << std::endl;
            } else {
                WatchFile file;
                file.type = "image";
                file.path = argument;
                file.lastChange = st.st_mtime;
                files.push_back(file);
            }
        }
    }

    // If no shader
    if( iFrag == -1 && iVert == -1 && iGeom == -1) {
        std::cerr << "Usage: " << argv[0] << " shader.frag [shader.vert] [mesh.(obj/.ply)] [texture.(png/jpg)] [-textureNameA texture.(png/jpg)] [-u] [-x x] [-y y] [-w width] [-h height] [-l/--livecoding] [--square] [-s seconds] [-o screenshot.png]\n";
        return EXIT_FAILURE;
    }

    // Fork process with a shared variable
    //
    int shmId = shmget(IPC_PRIVATE, sizeof(bool), 0666);
    pid_t pid = fork();
    iHasChanged = (int *) shmat(shmId, NULL, 0);

    switch(pid) {
        case -1: //error
        break;

        case 0: // child
        {
            *iHasChanged = -1;
            watchThread();
        }
        break;

        default:
        {
            // Initialize openGL context
            initGL(argc,argv);

            // OpenGL Render Loop
            renderThread(argc,argv);

            //  Kill the iNotify watcher once you finish
            kill(pid, SIGKILL);
            onExit();
        }
        break;
    }

    shmctl(shmId, IPC_RMID, NULL);
    return 0;
}

//  Watching Thread
//============================================================================
void watchThread() {
    struct stat st;
    while(1){
        for(uint i = 0; i < files.size(); i++){
            if( *iHasChanged == -1 ){
                stat(files[i].path.c_str(), &st);
                int date = st.st_mtime;
                if (date != files[i].lastChange ){
                    *iHasChanged = i;
                    files[i].lastChange = date;
                }
                usleep(500000);
            }
        }
    }
}

void renderThread(int argc, char **argv) {
    // Prepare viewport
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT );

    // Setup
    setup();

    // Turn on Alpha blending
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

    // Clear the background
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    int textureCounter = 0;

    //Load the the resources (textures)
    for (uint i = 1; i < argc ; i++){
        std::string argument = std::string(argv[i]);

        if (argument == "-x" || argument == "-y" ||
            argument == "-w" || argument == "--width" ||
            argument == "-h" || argument == "--height" ) {
            i++;
        } else if ( argument == "--square" ||
                    argument == "-l" ||
                    argument == "--life-coding"  ) {

        } else if ( argument == "-m" ) {
            bCursor = true;
            cursor.init();
        } else if ( argument == "-s" || argument == "--sec") {
            i++;
            argument = std::string(argv[i]);
            timeLimit = getFloat(argument);
            std::cout << "Will exit in " << timeLimit << " seconds." << std::endl;
        } else if ( argument == "-o" ){
            i++;
            argument = std::string(argv[i]);
            if( haveExt(argument,"png") ){
                outputFile = argument;
                std::cout << "Will save screenshot to " << outputFile  << " on exit." << std::endl;
            } else {
                std::cout << "At the moment screenshots only support PNG formats" << std::endl;
            }

        } else if (argument.find("-") == 0) {
            std::string parameterPair = argument.substr(argument.find_last_of('-')+1);

            i++;
            argument = std::string(argv[i]);
            Texture* tex = new Texture();
            if( tex->load(argument) ){
                textures[parameterPair] = tex;
                std::cout << "Loading " << argument << " as the following uniform: " << std::endl;
                std::cout << "    uniform sampler2D " << parameterPair  << "; // loaded"<< std::endl;
                std::cout << "    uniform vec2 " << parameterPair  << "Resolution;"<< std::endl;
            }

        } else if ( haveExt(argument,"png") || haveExt(argument,"PNG") ||
                    haveExt(argument,"jpg") || haveExt(argument,"JPG") ||
                    haveExt(argument,"jpeg") || haveExt(argument,"JPEG") ) {

            Texture* tex = new Texture();
            if( tex->load(argument) ){
                std::string name = "u_tex"+getString(textureCounter);
                textures[name] = tex;
                std::cout << "Loading " << argument << " as the following uniform: " << std::endl;
                std::cout << "    uniform sampler2D " << name  << "; // loaded"<< std::endl;
                std::cout << "    uniform vec2 " << name  << "Resolution;"<< std::endl;
                textureCounter++;
            }
        }
    }

    // Render Loop
    while (isGL() && bPlay) {
        // Update
        updateGL();

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Draw
        draw();

        // Swap the buffers
        renderGL();

        if ( timeLimit > 0.0 && getTime() > timeLimit ) {
            onKeyPress('s');
            bPlay = false;
        }
    }
}

void setup() {
    glEnable(GL_DEPTH_TEST);
    glFrontFace(GL_CCW);

    //  Load Geometry
    //
    if ( iGeom == -1 ){
        vbo = rect(0.0,0.0,1.0,1.0).getVbo();
    } else {
        Mesh model;
        model.load(files[iGeom].path);
        vbo = model.getVbo();
        glm::vec3 toCentroid = getCentroid(model.getVertices());
        // model_matrix = glm::scale(glm::vec3(0.001));
        model_matrix = glm::translate(-toCentroid);
    }

    //  Build shader;
    //
    if ( iFrag != -1 ) {
        fragSource = "";
        if(!loadFromPath(files[iFrag].path, &fragSource)) {
            return;
        }
    } else {
        fragSource = vbo->getVertexLayout()->getDefaultFragShader();
    }

    if ( iVert != -1 ) {
        vertSource = "";
        loadFromPath(files[iVert].path, &vertSource);
    } else {
        vertSource = vbo->getVertexLayout()->getDefaultVertShader();
    }
    shader.load(fragSource,vertSource);

    cam.setViewport(getWindowWidth(),getWindowHeight());
    cam.setPosition(glm::vec3(0.0,0.0,-3.));
}

void draw(){

    // Something change??
    if(*iHasChanged != -1) {
        onFileChange();
        *iHasChanged = -1;
    }

    shader.use();
    shader.setUniform("u_time", getTime());
    shader.setUniform("u_mouse", getMouseX(), getMouseY());
    shader.setUniform("u_resolution",getWindowWidth(), getWindowHeight());

    glm::mat4 mvp = glm::mat4(1.);
    if (iGeom != -1) {
        shader.setUniform("u_eye", -cam.getPosition());
        shader.setUniform("u_normalMatrix", cam.getNormalMatrix());

        shader.setUniform("u_modelMatrix", model_matrix);
        shader.setUniform("u_viewMatrix", cam.getViewMatrix());
        shader.setUniform("u_projectionMatrix", cam.getProjectionMatrix());

        mvp = cam.getProjectionViewMatrix() * model_matrix;
    }
    shader.setUniform("u_modelViewProjectionMatrix", mvp);

    unsigned int index = 0;
    for (std::map<std::string,Texture*>::iterator it = textures.begin(); it!=textures.end(); ++it) {
        shader.setUniform(it->first,it->second,index);
        shader.setUniform(it->first+"Resolution",it->second->getWidth(),it->second->getHeight());
        index++;
    }

    vbo->draw(&shader);

    if(bCursor){
        cursor.draw();
    }
}

// Rendering Thread
//============================================================================
void onFileChange(){
    std::string type = files[*iHasChanged].type;
    std::string path = files[*iHasChanged].path;

    if ( type == "fragment" ){
        fragSource = "";
        if(loadFromPath(path, &fragSource)){
            shader.detach(GL_FRAGMENT_SHADER | GL_VERTEX_SHADER);
            shader.load(fragSource,vertSource);
        }
    } else if ( type == "vertex" ){
        vertSource = "";
        if(loadFromPath(path, &vertSource)){
            shader.detach(GL_FRAGMENT_SHADER | GL_VERTEX_SHADER);
            shader.load(fragSource,vertSource);
        }
    } else if ( type == "geometry" ){
        // TODO
    } else if ( type == "image" ){
        for (std::map<std::string,Texture*>::iterator it = textures.begin(); it!=textures.end(); ++it) {
            if ( path == it->second->getFilePath() ){
                it->second->load(path);
                break;
            }
        }
    }
}

void onKeyPress(int _key) {
    if( _key == 'q' || _key == 'Q' || _key == 's' || _key == 'S' ){
        if (outputFile != "") {
            unsigned char* pixels = new unsigned char[getWindowWidth()*getWindowHeight()*4];
            glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE, pixels);
            Texture::savePixels(outputFile, pixels, getWindowWidth(), getWindowHeight());
        }
    }

    if ( _key == 'q' || _key == 'Q'){
        bPlay = false;
    }
}

void onMouseMove(float _x, float _y) {

}

void onMouseClick(float _x, float _y, int _button) {

}

void onMouseDrag(float _x, float _y, int _button) {
    if (_button == 1){
        float dist = glm::length(cam.getPosition());
        lat -= getMouseVelX();
        lon -= getMouseVelY()*0.5;
        cam.orbit(lat,lon,dist);
        cam.lookAt(glm::vec3(0.0));
    } else {
        float dist = glm::length(cam.getPosition());
        dist += (-.008f * getMouseVelY());
        if(dist > 0.0f){
            cam.setPosition( -dist * cam.getZAxis() );
            cam.lookAt(glm::vec3(0.0));
        }
    }
}

void onViewportResize(int _newWidth, int _newHeight) {
    cam.setViewport(_newWidth,_newHeight);
}

void onExit() {
    // clear screen
    glClear( GL_COLOR_BUFFER_BIT );

    // close openGL instance
    closeGL();

    // DELETE RESOURCES
    for (std::map<std::string,Texture*>::iterator i = textures.begin(); i != textures.end(); ++i) {
        delete i->second;
        i->second = NULL;
    }
    textures.clear();
    delete vbo;
}<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: testtoolloader.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 13:54:11 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "testtoolloader.hxx"

#ifndef _OSL_MODULE_H_
#include <osl/module.h>
#endif
#ifndef _OSL_FILE_HXX_
#include <osl/file.hxx>
#endif
#ifndef _RTL_LOGFILE_HXX_
#include <rtl/logfile.hxx>
#endif
#ifndef _VOS_PROCESS_HXX_
#include <vos/process.hxx>
#endif
#ifndef _SOLAR_H
#include "solar.h"
#endif
#ifndef _STRING_HXX
#include "string.hxx"
#endif
#ifndef _TOOLS_DEBUG_HXX
#include "debug.hxx"
#endif

using namespace rtl;

namespace tools
{
    typedef void ( *pfunc_CreateRemoteControl)();
    typedef void ( *pfunc_DestroyRemoteControl)();

static oslModule    aTestToolModule = 0;

sal_uInt32 GetCommandLineParamCount()
{
    NAMESPACE_VOS( OStartupInfo ) aStartInfo;
    return aStartInfo.getCommandArgCount();
}

String GetCommandLineParam( sal_uInt32 nParam )
{
    NAMESPACE_VOS( OStartupInfo ) aStartInfo;
    ::rtl::OUString aParam;
    NAMESPACE_VOS( OStartupInfo )::TStartupError eError = aStartInfo.getCommandArg( nParam, aParam );
    if ( eError == NAMESPACE_VOS( OStartupInfo )::E_None )
        return String( aParam );
    else
    {
        DBG_ERROR( "Unable to get CommandLineParam" );
        return String();
    }
}

void InitTestToolLib()
{
    RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::InitTestToolLib" );

    sal_uInt32 i;
    // are we to be automated at all?
    bool bAutomate = false;

    for ( i = 0 ; i < GetCommandLineParamCount() ; i++ )
    {
        if ( GetCommandLineParam( i ).EqualsIgnoreCaseAscii("/enableautomation")
            || GetCommandLineParam( i ).EqualsIgnoreCaseAscii("-enableautomation"))
        {
            bAutomate = true;
            break;
        }
    }

    if ( !bAutomate )
        return;

    OUString    aFuncName( RTL_CONSTASCII_USTRINGPARAM( "CreateRemoteControl" ));
    OUString    aModulePath;

    ::vos::OStartupInfo().getExecutableFile( aModulePath );
    sal_uInt32  lastIndex = aModulePath.lastIndexOf('/');
    if ( lastIndex > 0 )
        aModulePath = aModulePath.copy( 0, lastIndex+1 );

    aModulePath += OUString::createFromAscii( SVLIBRARY( "sts" ) );

    // Shortcut for Performance: We expect that the test tool library is not installed
    // (only for testing purpose). It should be located beside our executable.
    // We don't want to pay for searching through LD_LIBRARY_PATH so we check for
    // existence only in our executable path!!
    osl::DirectoryItem  aItem;
    osl::FileBase::RC   nResult = osl::DirectoryItem::get( aModulePath, aItem );

    if ( nResult == osl::FileBase::E_None )
    {
        aTestToolModule = osl_loadModule( aModulePath.pData, SAL_LOADMODULE_DEFAULT );
        if ( aTestToolModule )
        {
            oslGenericFunction pInitFunc = osl_getFunctionSymbol(
                aTestToolModule, aFuncName.pData );
            if ( pInitFunc )
                (reinterpret_cast< pfunc_CreateRemoteControl >(pInitFunc))();
            else
            {
                   DBG_ERROR1( "Unable to get Symbol 'CreateRemoteControl' from library %s while loading testtool support.", SVLIBRARY( "sts" ) );
            }
        }
        else
        {
               DBG_ERROR1( "Error loading library %s while loading testtool support.", SVLIBRARY( "sts" ) );
        }
    }
    else
    {
        DBG_ERROR1( "Unable to access library %s while loading testtool support.", SVLIBRARY( "sts" ) );
    }
}

void DeInitTestToolLib()
{
    if ( aTestToolModule )
    {
        OUString    aFuncName( RTL_CONSTASCII_USTRINGPARAM( "DestroyRemoteControl" ));

        oslGenericFunction pDeInitFunc = osl_getFunctionSymbol(
            aTestToolModule, aFuncName.pData );
        if ( pDeInitFunc )
            (reinterpret_cast< pfunc_DestroyRemoteControl >(pDeInitFunc))();

        osl_unloadModule( aTestToolModule );
    }
}

} // namespace tools
<commit_msg>INTEGRATION: CWS pchfix02 (1.5.42); FILE MERGED 2006/09/01 17:54:59 kaib 1.5.42.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: testtoolloader.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 01:05:15 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_tools.hxx"

#include "testtoolloader.hxx"

#ifndef _OSL_MODULE_H_
#include <osl/module.h>
#endif
#ifndef _OSL_FILE_HXX_
#include <osl/file.hxx>
#endif
#ifndef _RTL_LOGFILE_HXX_
#include <rtl/logfile.hxx>
#endif
#ifndef _VOS_PROCESS_HXX_
#include <vos/process.hxx>
#endif
#ifndef _SOLAR_H
#include "solar.h"
#endif
#ifndef _STRING_HXX
#include "string.hxx"
#endif
#ifndef _TOOLS_DEBUG_HXX
#include "debug.hxx"
#endif

using namespace rtl;

namespace tools
{
    typedef void ( *pfunc_CreateRemoteControl)();
    typedef void ( *pfunc_DestroyRemoteControl)();

static oslModule    aTestToolModule = 0;

sal_uInt32 GetCommandLineParamCount()
{
    NAMESPACE_VOS( OStartupInfo ) aStartInfo;
    return aStartInfo.getCommandArgCount();
}

String GetCommandLineParam( sal_uInt32 nParam )
{
    NAMESPACE_VOS( OStartupInfo ) aStartInfo;
    ::rtl::OUString aParam;
    NAMESPACE_VOS( OStartupInfo )::TStartupError eError = aStartInfo.getCommandArg( nParam, aParam );
    if ( eError == NAMESPACE_VOS( OStartupInfo )::E_None )
        return String( aParam );
    else
    {
        DBG_ERROR( "Unable to get CommandLineParam" );
        return String();
    }
}

void InitTestToolLib()
{
    RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::InitTestToolLib" );

    sal_uInt32 i;
    // are we to be automated at all?
    bool bAutomate = false;

    for ( i = 0 ; i < GetCommandLineParamCount() ; i++ )
    {
        if ( GetCommandLineParam( i ).EqualsIgnoreCaseAscii("/enableautomation")
            || GetCommandLineParam( i ).EqualsIgnoreCaseAscii("-enableautomation"))
        {
            bAutomate = true;
            break;
        }
    }

    if ( !bAutomate )
        return;

    OUString    aFuncName( RTL_CONSTASCII_USTRINGPARAM( "CreateRemoteControl" ));
    OUString    aModulePath;

    ::vos::OStartupInfo().getExecutableFile( aModulePath );
    sal_uInt32  lastIndex = aModulePath.lastIndexOf('/');
    if ( lastIndex > 0 )
        aModulePath = aModulePath.copy( 0, lastIndex+1 );

    aModulePath += OUString::createFromAscii( SVLIBRARY( "sts" ) );

    // Shortcut for Performance: We expect that the test tool library is not installed
    // (only for testing purpose). It should be located beside our executable.
    // We don't want to pay for searching through LD_LIBRARY_PATH so we check for
    // existence only in our executable path!!
    osl::DirectoryItem  aItem;
    osl::FileBase::RC   nResult = osl::DirectoryItem::get( aModulePath, aItem );

    if ( nResult == osl::FileBase::E_None )
    {
        aTestToolModule = osl_loadModule( aModulePath.pData, SAL_LOADMODULE_DEFAULT );
        if ( aTestToolModule )
        {
            oslGenericFunction pInitFunc = osl_getFunctionSymbol(
                aTestToolModule, aFuncName.pData );
            if ( pInitFunc )
                (reinterpret_cast< pfunc_CreateRemoteControl >(pInitFunc))();
            else
            {
                   DBG_ERROR1( "Unable to get Symbol 'CreateRemoteControl' from library %s while loading testtool support.", SVLIBRARY( "sts" ) );
            }
        }
        else
        {
               DBG_ERROR1( "Error loading library %s while loading testtool support.", SVLIBRARY( "sts" ) );
        }
    }
    else
    {
        DBG_ERROR1( "Unable to access library %s while loading testtool support.", SVLIBRARY( "sts" ) );
    }
}

void DeInitTestToolLib()
{
    if ( aTestToolModule )
    {
        OUString    aFuncName( RTL_CONSTASCII_USTRINGPARAM( "DestroyRemoteControl" ));

        oslGenericFunction pDeInitFunc = osl_getFunctionSymbol(
            aTestToolModule, aFuncName.pData );
        if ( pDeInitFunc )
            (reinterpret_cast< pfunc_DestroyRemoteControl >(pDeInitFunc))();

        osl_unloadModule( aTestToolModule );
    }
}

} // namespace tools
<|endoftext|>


<commit_before>#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <iostream>
#include "draw.hpp"
#include "math.hpp"
#include "vectors.hpp"
#include "window.hpp"
#include "shader.hpp"
#include "font.hpp"

vec3s camera = {5,M_PI/4,0}; // положение камеры в сферических координатах
vec3s sun_pos = {3, M_PI/2,M_PI/2};
float dtheta = 0.01;
float dphi = 0.01;
GLuint program;
gSphere sphere( 1.0f, 30, 60 );
gSphere sun( 0.2f, 30, 60 );
gFont font;

//float light_position[4] = {2.0, 2.0, 2.0, 1.0};

int rows = 30;
int cols = 60;
GLubyte* cells;
field* f;

WindowManager window( "Game Of Life On fieldace" );

void golos_init( void ) {
    // init OpenGL params
    glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
    glClearDepth( 1.0 );
    glDepthFunc( GL_LESS );
    glEnable( GL_DEPTH_TEST );
    glShadeModel( GL_SMOOTH );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluPerspective( 60.0f, (float) window.GetWidth() / (float) window.GetHeight(), 0.1f, 100.0f );
    glMatrixMode( GL_MODELVIEW );
    glewInit();

    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);

    program = glCreateProgram();
    auto shader = compileShader( "./shaders/fragment.glsl", GL_FRAGMENT_SHADER );
    glAttachShader( program, shader );
    shader = compileShader( "./shaders/vertex.glsl", GL_VERTEX_SHADER );
    glAttachShader( program, shader );
    glLinkProgram( program );
    printInfoLog( program );

    f = new field( rows, cols );
    // рандомная инициализация
    for ( int i = 0; i < rows; ++i )
        for ( int j = 0; j < cols; ++j )
            (*f)[i][j] = rand() % 2;
    cells = new GLubyte[rows * cols];

    font.load( "./data/OpenSansLight.ttf", 16 );
}

void golos_event( SDL_Event * event ) {
    SDL_PollEvent( event );
    switch ( event->type ) {
        case SDL_QUIT:
            window.KillWindow();
            break;
        case SDL_KEYDOWN:
            switch ( event->key.keysym.sym ) {
                case SDLK_SPACE:
                    f->nextGeneration();
                    break;
                case SDLK_ESCAPE:
                case SDLK_q:
                    window.KillWindow();
                    break;
                case SDLK_DOWN:
                    camera.rotate(dtheta, 0);
                    break;
                case SDLK_UP:
                    camera.rotate(-dtheta, 0);
                    break;
                case SDLK_RIGHT:
                    camera.rotate(0, dphi);
                    break;
                case SDLK_LEFT:
                    camera.rotate(0, -dphi);
                    break;
                default:
                    break;
            }
            break;
        default:
            break;
    }
}

void golos_render( void ) {
    vec3d rect_camera = vec3d(camera); // положение камеры в прямоугольных координатах
    vec3d rect_sun = vec3d(sun_pos);
    sun_pos.rotate(0, dphi/3);

    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glLoadIdentity();

    float up = (camera.theta < 0) ? -1.0 : 1.0; // фикс для gluLookAt
    gluLookAt( rect_camera.x, rect_camera.y, rect_camera.z, 0, 0, 0, 0, 0, up );

    // рисуем солнышко (потом добавлю шейдер)
    glPushMatrix();
        glTranslatef(rect_sun.x, rect_sun.y, rect_sun.z);
        glColor3f(1.0, 1.0, 0.0);
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        sun.draw();
        float light_position[4] = {0, 0, 0, 1};
        glLightfv(GL_LIGHT0, GL_POSITION, light_position);
    glPopMatrix();

    // врубаем шейдеры
    glUseProgram( program );

    // формируем текстуру

    for ( int i = 0; i < rows; ++i )
        for ( int j = 0; j < cols; ++j )
            cells[i * cols + j] = ( (*f)[i][j] ) ? 0xff : 0x00;

    // отдаём текстуру
    glBindTexture( GL_TEXTURE_2D, 1 );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, cols, rows, 0, GL_RED , GL_UNSIGNED_BYTE, cells );
    glEnable( GL_TEXTURE_2D );
    glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );

    // рисуем сферу
    sphere.draw();

    glUseProgram( 0 );

    // для нормального отображения текста
    glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
    glPushMatrix();
    glLoadIdentity();
    glColor3f( 1.0f, 1.0f, 1.0f );
    font.draw( 10, 10, "FPS: %.2f", window.GetFPS() );
    glPopMatrix();

    glFlush();
}

void golos_destroy( void ) {
    delete[] cells;
}

int main( int argc, char ** argv ) {
    window.SetInitFunc( golos_init );
    window.SetRenderFunc( golos_render );
    window.SetEventFunc( golos_event );
    window.MainLoop();
    golos_destroy();
    return EXIT_SUCCESS;
}
<commit_msg>[add] move camera by mouse<commit_after>#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <iostream>
#include "draw.hpp"
#include "math.hpp"
#include "vectors.hpp"
#include "window.hpp"
#include "shader.hpp"
#include "font.hpp"

vec3s camera = {5,M_PI/4,0}; // положение камеры в сферических координатах
vec3s sun_pos = {3, M_PI/2,M_PI/2};
float dtheta = 0.01;
float dphi = 0.01;
GLuint program;
gSphere sphere( 1.0f, 30, 60 );
gSphere sun( 0.2f, 30, 60 );
gFont font;

//float light_position[4] = {2.0, 2.0, 2.0, 1.0};

int rows = 30;
int cols = 60;
GLubyte* cells;
field* f;

WindowManager window( "Game Of Life On fieldace" );

void golos_init( void ) {
    // init OpenGL params
    glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
    glClearDepth( 1.0 );
    glDepthFunc( GL_LESS );
    glEnable( GL_DEPTH_TEST );
    glShadeModel( GL_SMOOTH );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluPerspective( 60.0f, (float) window.GetWidth() / (float) window.GetHeight(), 0.1f, 100.0f );
    glMatrixMode( GL_MODELVIEW );
    glewInit();

    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);

    program = glCreateProgram();
    auto shader = compileShader( "./shaders/fragment.glsl", GL_FRAGMENT_SHADER );
    glAttachShader( program, shader );
    shader = compileShader( "./shaders/vertex.glsl", GL_VERTEX_SHADER );
    glAttachShader( program, shader );
    glLinkProgram( program );
    printInfoLog( program );

    f = new field( rows, cols );
    // рандомная инициализация
    for ( int i = 0; i < rows; ++i )
        for ( int j = 0; j < cols; ++j )
            (*f)[i][j] = rand() % 2;
    cells = new GLubyte[rows * cols];

    font.load( "./data/OpenSansLight.ttf", 16 );
}

void golos_event( SDL_Event * event ) {
    static uint8_t button_left_set = false;
    static uint8_t button_right_set = false;
    static uint16_t mouse_x = 0, mouse_y = 0;
    SDL_PollEvent( event );
    switch ( event->type ) {
        case SDL_QUIT:
            window.KillWindow();
            break;
        case SDL_KEYDOWN:
            switch ( event->key.keysym.sym ) {
                case SDLK_SPACE:
                    f->nextGeneration();
                    break;
                case SDLK_ESCAPE:
                case SDLK_q:
                    window.KillWindow();
                    break;
                case SDLK_DOWN:
                    camera.rotate(dtheta, 0);
                    break;
                case SDLK_UP:
                    camera.rotate(-dtheta, 0);
                    break;
                case SDLK_RIGHT:
                    camera.rotate(0, dphi);
                    break;
                case SDLK_LEFT:
                    camera.rotate(0, -dphi);
                    break;
                default:
                    break;
            }
            break;
        case SDL_MOUSEMOTION:
            if ( button_left_set ) {
                camera.rotate( -( event->button.y - mouse_y ) / 100.0f,
                               -( event->button.x - mouse_x ) / 100.0f );
                mouse_x = event->button.x;
                mouse_y = event->button.y;
            }
            break;
        case SDL_MOUSEBUTTONDOWN:
            switch ( event->button.button ) {
                case SDL_BUTTON_LEFT:
                    if ( !button_left_set ) {
                        mouse_x = event->button.x;
                        mouse_y = event->button.y;
                    }
                    button_left_set = true;
                    break;
                case SDL_BUTTON_RIGHT:
                    button_right_set = true;
                    break;
                default:
                    break;
            }
            break;
        case SDL_MOUSEBUTTONUP:
            button_left_set = button_right_set = false;
            break;
        default:
            break;
    }
}

void golos_render( void ) {
    vec3d rect_camera = vec3d(camera); // положение камеры в прямоугольных координатах
    vec3d rect_sun = vec3d(sun_pos);
    sun_pos.rotate(0, dphi/3);

    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glLoadIdentity();

    float up = (camera.theta < 0) ? -1.0 : 1.0; // фикс для gluLookAt
    gluLookAt( rect_camera.x, rect_camera.y, rect_camera.z, 0, 0, 0, 0, 0, up );

    // рисуем солнышко (потом добавлю шейдер)
    glPushMatrix();
        glTranslatef(rect_sun.x, rect_sun.y, rect_sun.z);
        glColor3f(1.0, 1.0, 0.0);
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        sun.draw();
        float light_position[4] = {0, 0, 0, 1};
        glLightfv(GL_LIGHT0, GL_POSITION, light_position);
    glPopMatrix();

    // врубаем шейдеры
    glUseProgram( program );

    // формируем текстуру

    for ( int i = 0; i < rows; ++i )
        for ( int j = 0; j < cols; ++j )
            cells[i * cols + j] = ( (*f)[i][j] ) ? 0xff : 0x00;

    // отдаём текстуру
    glBindTexture( GL_TEXTURE_2D, 1 );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, cols, rows, 0, GL_RED , GL_UNSIGNED_BYTE, cells );
    glEnable( GL_TEXTURE_2D );
    glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );

    // рисуем сферу
    sphere.draw();

    glUseProgram( 0 );

    // для нормального отображения текста
    glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
    glPushMatrix();
    glLoadIdentity();
    glColor3f( 1.0f, 1.0f, 1.0f );
    font.draw( 10, 10, "FPS: %.2f", window.GetFPS() );
    glPopMatrix();

    glFlush();
}

void golos_destroy( void ) {
    delete[] cells;
}

int main( int argc, char ** argv ) {
    window.SetInitFunc( golos_init );
    window.SetRenderFunc( golos_render );
    window.SetEventFunc( golos_event );
    window.MainLoop();
    golos_destroy();
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <string>
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <string.h>

#define STATIC_STRING_VARIABLE_NAME "__serenity_templater_str"
#define RESULT_VARIABLE_NAME "__serenity_templater_res"

static void writeText(std::ostream & out, const std::string & text) {
	out << "{static const char " STATIC_STRING_VARIABLE_NAME "[]={";
	out << std::to_string(text[0]);
	for (auto it = ++text.begin(); it != text.end(); it++) { out << ',' << std::to_string(*it); }
	out << ",0";
	out << "};" RESULT_VARIABLE_NAME "<<" STATIC_STRING_VARIABLE_NAME ";}";
}

static void writeCommand(std::ostream & out, const std::string & command, const std::string & parameters) {
	if ((command == "") && (parameters == "")) return;            // так надо

	// simple expression
	if (command == "")        out << RESULT_VARIABLE_NAME "<<" << parameters << ";"; else         // $(var)
	// commands without parameters
	if (command == "else")    out << "}else{"; else                        // $else
	if (command == "end")     out << '}'; else                          // $end
	// commands with parameters
	if (parameters == "")     out << RESULT_VARIABLE_NAME "<<" << command << ";"; else            // $var
	//if (command == "import")  return preprocess::file(parameters); else   // $import(file.htmlt)
	//if (command == "include") return include(parameters); else            // $include(file.css)
	if (command == "for")     out << "for(" << parameters << "){"; else               // $for (int i=0; else i<n; else i++)
	if (command == "foreach") out << "for(const auto&" << parameters << "){"; else            // $foreach(item : collection)
	if (command == "if")      out << "if(" << parameters << "){"; else                // $if (cond)

	throw std::runtime_error("unknown command: $'" + command + "'('" + parameters + "')");
}

static void preprocess(std::istream & in, std::ostream & out, const std::string & templateName) {
	out << "#define __SERENITY_TEMPLATER_TEMPLATE_" << templateName << " [&](){std::stringstream " RESULT_VARIABLE_NAME ";";

	enum class State {
		TEXT,                      // skipping to $
		DOLLAR_COMMAND_NAME,       // skipping to ( or non-alphanumeric
		DOLLAR_COMMAND_PARAMETERS  // skipping to matching )
	};

	State state = State::TEXT;
	std::string text;
	std::string command;
	std::string parameters;
	int bracketsDepth = 0;

	for (int c_int = in.get(); (c_int != std::char_traits<char>::eof()) && (in.good()); c_int = in.get()) {
		char c = (char)c_int;
		State newState = state;

		if (state == State::TEXT) {
			if (c == '$') { newState = State::DOLLAR_COMMAND_NAME; } else { text += c; }
		} else if (state == State::DOLLAR_COMMAND_NAME) {
			if (isalnum(c) || (c == '_')) {
				command += c;
			} else if (c == '(') {
				newState = State::DOLLAR_COMMAND_PARAMETERS;
				bracketsDepth = 1;
			} else {
				newState = State::TEXT;
				if ((c == '$') && command.empty()) { text += c; } else { in.putback(c); }
			}
		} else if (state == State::DOLLAR_COMMAND_PARAMETERS) {
			if (c == '(') { bracketsDepth++; }
			if (c == ')') { bracketsDepth--; }
			if (bracketsDepth > 0) { parameters += c; } else { newState = State::TEXT; }
		}

		if (newState != state) {
			if (newState == State::TEXT) {
				if (!text.empty()) writeText(out, text);
				if (!command.empty() || !parameters.empty()) writeCommand(out, command, parameters);

				text.clear();
				command.clear();
				parameters.clear();
			}

			state = newState;
		}
	}

	if (!text.empty()) writeText(out, text);
	if (!command.empty() || !parameters.empty()) writeCommand(out, command, parameters);

	out << "return " RESULT_VARIABLE_NAME ".str();}\n";
}

static std::string fileNameToTemplateName(const std::string & fileName) {
	auto begin = fileName.find_last_of('/');
	if (begin == std::string::npos) begin = 0;
	auto end = fileName.find('.', begin);
	if (end == std::string::npos) end = fileName.size()-1;
	return fileName.substr(begin+1, end-begin-1);
}

int main(int argc, char ** argv) {
	if ((argc < 2) || (strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {
		printf("Usage:\n  %s output-file.htmltc input-file1.htmlt ... input-fileN.htmlt", argv[0]);
		return 1;
	}

	std::ofstream out(argv[1]);
	out << "#include <serenity/templater.hpp>\n";
	for (int i=2; i<argc; i++) {
  	std::ifstream in(argv[i], std::ios::in | std::ios::binary);
		preprocess(in, out, fileNameToTemplateName(argv[i]));
	}
	return 0;
}
<commit_msg>use std::stringstream::write<commit_after>#include <string>
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <string.h>

#define STATIC_STRING_VARIABLE_NAME "__serenity_templater_str"
#define RESULT_VARIABLE_NAME "__serenity_templater_res"

static void writeText(std::ostream & out, const std::string & text) {
	out << "{static const char " STATIC_STRING_VARIABLE_NAME "[]={";
	out << std::to_string(text[0]);
	for (auto it = ++text.begin(); it != text.end(); it++) { out << ',' << std::to_string(*it); }
	out << "};" RESULT_VARIABLE_NAME ".write(" STATIC_STRING_VARIABLE_NAME ",sizeof(" STATIC_STRING_VARIABLE_NAME "));}";
}

static void writeCommand(std::ostream & out, const std::string & command, const std::string & parameters) {
	if ((command == "") && (parameters == "")) return;            // так надо

	// simple expression
	if (command == "")        out << RESULT_VARIABLE_NAME "<<" << parameters << ";"; else         // $(var)
	// commands without parameters
	if (command == "else")    out << "}else{"; else                        // $else
	if (command == "end")     out << '}'; else                          // $end
	// commands with parameters
	if (parameters == "")     out << RESULT_VARIABLE_NAME "<<" << command << ";"; else            // $var
	//if (command == "import")  return preprocess::file(parameters); else   // $import(file.htmlt)
	//if (command == "include") return include(parameters); else            // $include(file.css)
	if (command == "for")     out << "for(" << parameters << "){"; else               // $for (int i=0; else i<n; else i++)
	if (command == "foreach") out << "for(const auto&" << parameters << "){"; else            // $foreach(item : collection)
	if (command == "if")      out << "if(" << parameters << "){"; else                // $if (cond)

	throw std::runtime_error("unknown command: $'" + command + "'('" + parameters + "')");
}

static void preprocess(std::istream & in, std::ostream & out, const std::string & templateName) {
	out << "#define __SERENITY_TEMPLATER_TEMPLATE_" << templateName << " [&](){std::stringstream " RESULT_VARIABLE_NAME ";";

	enum class State {
		TEXT,                      // skipping to $
		DOLLAR_COMMAND_NAME,       // skipping to ( or non-alphanumeric
		DOLLAR_COMMAND_PARAMETERS  // skipping to matching )
	};

	State state = State::TEXT;
	std::string text;
	std::string command;
	std::string parameters;
	int bracketsDepth = 0;

	for (int c_int = in.get(); (c_int != std::char_traits<char>::eof()) && (in.good()); c_int = in.get()) {
		char c = (char)c_int;
		State newState = state;

		if (state == State::TEXT) {
			if (c == '$') { newState = State::DOLLAR_COMMAND_NAME; } else { text += c; }
		} else if (state == State::DOLLAR_COMMAND_NAME) {
			if (isalnum(c) || (c == '_')) {
				command += c;
			} else if (c == '(') {
				newState = State::DOLLAR_COMMAND_PARAMETERS;
				bracketsDepth = 1;
			} else {
				newState = State::TEXT;
				if ((c == '$') && command.empty()) { text += c; } else { in.putback(c); }
			}
		} else if (state == State::DOLLAR_COMMAND_PARAMETERS) {
			if (c == '(') { bracketsDepth++; }
			if (c == ')') { bracketsDepth--; }
			if (bracketsDepth > 0) { parameters += c; } else { newState = State::TEXT; }
		}

		if (newState != state) {
			if (newState == State::TEXT) {
				if (!text.empty()) writeText(out, text);
				if (!command.empty() || !parameters.empty()) writeCommand(out, command, parameters);

				text.clear();
				command.clear();
				parameters.clear();
			}

			state = newState;
		}
	}

	if (!text.empty()) writeText(out, text);
	if (!command.empty() || !parameters.empty()) writeCommand(out, command, parameters);

	out << "return " RESULT_VARIABLE_NAME ".str();}\n";
}

static std::string fileNameToTemplateName(const std::string & fileName) {
	auto begin = fileName.find_last_of('/');
	if (begin == std::string::npos) begin = 0;
	auto end = fileName.find('.', begin);
	if (end == std::string::npos) end = fileName.size()-1;
	return fileName.substr(begin+1, end-begin-1);
}

int main(int argc, char ** argv) {
	if ((argc < 2) || (strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {
		printf("Usage:\n  %s output-file.htmltc input-file1.htmlt ... input-fileN.htmlt", argv[0]);
		return 1;
	}

	std::ofstream out(argv[1]);
	out << "#include <serenity/templater.hpp>\n";
	for (int i=2; i<argc; i++) {
  	std::ifstream in(argv[i], std::ios::in | std::ios::binary);
		preprocess(in, out, fileNameToTemplateName(argv[i]));
	}
	return 0;
}
<|endoftext|>


<commit_before>/* BSD 3-Clause License:
 * Copyright (c) 2018, bitsofcotton.
 * 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 or other materials provided with the distribution.
 *    Neither 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.
 */

#if !defined(_2D3D_PSEUDO_)

#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <Eigen/Core>
#include <Eigen/Dense>

using std::complex;
using std::abs;
using std::vector;
using std::sort;
using std::max;
using std::min;
using std::sqrt;
using std::exp;
using std::pow;
using std::isfinite;
using std::cerr;
using std::flush;
using std::vector;

template <typename T> class PseudoBump {
public:
  typedef complex<T> U;
  typedef Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> Mat;
  typedef Eigen::Matrix<T, Eigen::Dynamic, 1>              Vec;
  typedef Eigen::Matrix<U, Eigen::Dynamic, Eigen::Dynamic> MatU;
  typedef Eigen::Matrix<T,   3, 1> Vec3;
  typedef Eigen::Matrix<int, 3, 1> Veci3;

  PseudoBump();
  ~PseudoBump();
  void initialize(const int& stp);
  void getPseudoVec(const Mat& in, vector<Vec3>& geoms, vector<Veci3>& delaunay, const int& vbox = 3, const T& rz = T(1) / T(8));
  Mat  getPseudoBump(const Mat& in);

private:
  Vec      getPseudoBumpSub(const Vec& work, const Mat& cf);
  const T& getImgPt(const Vec& img, const T& y);
  Mat      prepareLineAxis(const T& rstp);

  Mat Dops;
};

template <typename T> PseudoBump<T>::PseudoBump() {
  initialize(21);
}

template <typename T> PseudoBump<T>::~PseudoBump() {
  ;
}

template <typename T> void PseudoBump<T>::initialize(const int& stp) {
  assert(4 < stp);
  const T Pi(T(4) * atan2(T(1), T(1)));
  MatU DFT(stp / 2, stp / 2), IDFT(stp / 2, stp / 2);
  for(int i = 0; i < DFT.rows(); i ++)
    for(int j = 0; j < DFT.cols(); j ++) {
      DFT( i, j) = exp(U(- 2.) * Pi * sqrt(U(- 1)) * U(i * j / T(DFT.rows())));
      IDFT(i, j) = exp(U(  2.) * Pi * sqrt(U(- 1)) * U(i * j / T(DFT.rows()))) / T(DFT.rows());
    }
  for(int i = 0; i < DFT.rows(); i ++)
    DFT.row(i) *= - U(2.) * Pi * sqrt(U(- 1)) * T(i) / T(DFT.rows());
  const auto DopL((IDFT.row(IDFT.rows() - 1) * DFT).real().template cast<T>());
  const auto DopM((IDFT.row(IDFT.rows() / 2) * DFT).real().template cast<T>());
  const auto DopR((IDFT.row(0)               * DFT).real().template cast<T>());
  Dops = Mat(3, stp);
  for(int i = 0; i < Dops.cols(); i ++)
    Dops(0, i) = Dops(1, i) = Dops(2, i) = T(0);
  for(int i = 0; i < DopL.size(); i ++) {
    Dops(0, i)                                     = DopL[i];
    Dops(1, i - DopM.size() / 2 + Dops.cols() / 2) = DopM[i];
    Dops(2, i - DopR.size()     + Dops.cols()    ) = DopR[i];
  }
  return;
}

template <typename T> Eigen::Matrix<T, Eigen::Dynamic, 1> PseudoBump<T>::getPseudoBumpSub(const Vec& work, const Mat& cf) {
  cerr << "." << flush;
  Vec result(work.size());
  for(int s = 0; s < work.size(); s ++) {
    T sum(0);
    result[s] = T(0);
    for(int z = 0; z < cf.rows(); z ++) {
      // d/dt (local color) / ||local color||:
      Vec c(cf.cols());
      for(int u = 0; u < c.size(); u ++)
        c[u] = getImgPt(work, cf(z, u) + s);
      const auto buf(Dops * c);
      // N.B. <tangents, const distances> / <tangents, 1> is the result,
      //      this is quite pseudo because this similar to
      //      |tan(theta)| * d / |tan(theta)| / 1..
      const auto score(sqrt(buf.dot(buf) / c.dot(c)));
      if(isfinite(score)) {
        result[s] += score * pow(z / T(cf.rows()), T(2));
        sum       += score;
      }
    }
    result[s] /= sum;
  }
  return result;
}

template <typename T> Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> PseudoBump<T>::getPseudoBump(const Mat& in) {
  const auto cf(prepareLineAxis(sqrt(T(in.rows() * in.cols()))));
  Mat result(in.rows(), in.cols());
#if defined(_OPENMP)
#pragma omp parallel for schedule(static, 1)
#endif
  for(int i = 0; i < in.cols(); i ++)
    result.col(i)  = getPseudoBumpSub(in.col(i), cf);
#if defined(_OPENMP)
#pragma omp parallel for schedule(static, 1)
#endif
  for(int i = 0; i < in.rows(); i ++)
    result.row(i) += getPseudoBumpSub(in.row(i), cf);
  return result;
}

// get bump with multiple scale and vectorized result.
template <typename T> void PseudoBump<T>::getPseudoVec(const Mat& in, vector<Vec3>& geoms, vector<Veci3>& delaunay, const int& vbox, const T& rz) {
  assert(0 < vbox && T(0) < rz);
  // get vectorize.
  geoms = vector<Vec3>();
  T aavg(0);
  for(int i = 0; i < in.rows(); i ++)
    for(int j = 0; j < in.cols(); j ++)
      aavg += in(i, j);
  aavg /= in.rows() * in.cols();
  for(int i = 0; i < in.rows() / vbox + 1; i ++)
    for(int j = 0; j < in.cols() / vbox + 1; j ++) {
      if(in.rows() < (i + 1) * vbox ||
         in.cols() < (j + 1) * vbox) {
        if(geoms.size() >= 1) {
          Vec3 gbuf;
          gbuf[0] = i * vbox;
          gbuf[1] = j * vbox;
          gbuf[2] = geoms[geoms.size() - 1][2];
          geoms.push_back(gbuf);
        }
        continue;
      }
      T avg(0);
      for(int ii = i * vbox; ii < (i + 1) * vbox; ii ++)
        for(int jj = j * vbox; jj < (j + 1) * vbox; jj ++)
          avg += in(ii, jj);
      Vec3 work;
      work[0] = i * vbox;
      work[1] = j * vbox;
      const T intens(avg / vbox / vbox - aavg);
      work[2] = - intens * sqrt(T(in.rows() * in.cols())) * rz;
      geoms.push_back(work);
    }
  Vec3 avg;
  avg[0] = avg[1] = avg[2] = T(0);
  for(int i = 0; i < geoms.size(); i ++)
    avg += geoms[i];
  avg /= geoms.size();
  for(int i = 0; i < geoms.size(); i ++)
    geoms[i][2] -= avg[2];
  delaunay = vector<Veci3>();
  for(int i = 1; i < in.rows() / vbox + 1; i ++)
    for(int j = 0; j < in.cols() / vbox; j ++) {
      Veci3 work, work2;
      work[0]  = (i - 1) * (in.cols() / vbox + 1) + j;
      work[1]  =  i      * (in.cols() / vbox + 1) + j;
      work[2]  =  i      * (in.cols() / vbox + 1) + j + 1;
      work2[0] = (i - 1) * (in.cols() / vbox + 1) + j;
      work2[2] = (i - 1) * (in.cols() / vbox + 1) + j + 1;
      work2[1] =  i      * (in.cols() / vbox + 1) + j + 1;
      delaunay.push_back(work);
      delaunay.push_back(work2);
    }
  return;
}

template <typename T> Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> PseudoBump<T>::prepareLineAxis(const T& rstp) {
  Vec camera(2);
  camera[0] =   T(0);
  camera[1] = - T(1);

  Mat result(int(rstp), Dops.cols());
  T   absmax(0);
#if defined(_OPENMP)
#pragma omp parallel for schedule(static, 1)
#endif
  for(int zi = 0; zi < result.rows(); zi ++)
    for(int s = 0; s < result.cols(); s ++) {
      Vec cpoint(2);
      cpoint[0] = s / T(result.cols() - 1) - 1 / T(2);
      // [1, rstp] works well and scaling works rapidly better.
      cpoint[1] = (T(1) - pow(zi / T(result.rows()), T(2))) * rstp * T(2);
      // x-z plane projection of point p with camera geometry c to z=0.
      // c := camera, p := cpoint.
      // <c + (p - c) * t, [0, 1]> = 0
      const T t(- camera[1] / (cpoint[1] - camera[1]));
      result(zi, s) = (camera + (cpoint - camera) * t)[0];
#if defined(_OPENMP)
#pragma omp atomic
#endif
      absmax = max(abs(result(zi, s)), absmax);
    }
  return result * rstp / absmax;
}

template <typename T> const T& PseudoBump<T>::getImgPt(const Vec& img, const T& y) {
  const int& h(img.size());
  const int  yy(abs((int(y + .5) + 3 * h) % (2 * h) - h) % h);
  return img[yy];
}

#define _2D3D_PSEUDO_
#endif

<commit_msg>revert.<commit_after>/* BSD 3-Clause License:
 * Copyright (c) 2018, bitsofcotton.
 * 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 or other materials provided with the distribution.
 *    Neither 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.
 */

#if !defined(_2D3D_PSEUDO_)

#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <Eigen/Core>
#include <Eigen/Dense>

using std::complex;
using std::abs;
using std::vector;
using std::sort;
using std::max;
using std::min;
using std::sqrt;
using std::exp;
using std::pow;
using std::isfinite;
using std::cerr;
using std::flush;
using std::vector;

template <typename T> class PseudoBump {
public:
  typedef complex<T> U;
  typedef Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> Mat;
  typedef Eigen::Matrix<T, Eigen::Dynamic, 1>              Vec;
  typedef Eigen::Matrix<U, Eigen::Dynamic, Eigen::Dynamic> MatU;
  typedef Eigen::Matrix<T,   3, 1> Vec3;
  typedef Eigen::Matrix<int, 3, 1> Veci3;

  PseudoBump();
  ~PseudoBump();
  void initialize(const int& stp);
  void getPseudoVec(const Mat& in, vector<Vec3>& geoms, vector<Veci3>& delaunay, const int& vbox = 3, const T& rz = T(1) / T(8));
  Mat  getPseudoBump(const Mat& in);

private:
  Vec      getPseudoBumpSub(const Vec& work, const Mat& cf);
  const T& getImgPt(const Vec& img, const T& y);
  Mat      prepareLineAxis(const T& rstp);

  Mat Dops;
};

template <typename T> PseudoBump<T>::PseudoBump() {
  initialize(21);
}

template <typename T> PseudoBump<T>::~PseudoBump() {
  ;
}

template <typename T> void PseudoBump<T>::initialize(const int& stp) {
  assert(4 < stp);
  const T Pi(T(4) * atan2(T(1), T(1)));
  MatU DFT(stp / 2, stp / 2), IDFT(stp / 2, stp / 2);
  for(int i = 0; i < DFT.rows(); i ++)
    for(int j = 0; j < DFT.cols(); j ++) {
      DFT( i, j) = exp(U(- 2.) * Pi * sqrt(U(- 1)) * U(i * j / T(DFT.rows())));
      IDFT(i, j) = exp(U(  2.) * Pi * sqrt(U(- 1)) * U(i * j / T(DFT.rows()))) / T(DFT.rows());
    }
  for(int i = 0; i < DFT.rows(); i ++)
    DFT.row(i) *= - U(2.) * Pi * sqrt(U(- 1)) * T(i) / T(DFT.rows());
  const auto DopL((IDFT.row(IDFT.rows() - 1) * DFT).real().template cast<T>());
  const auto DopM((IDFT.row(IDFT.rows() / 2) * DFT).real().template cast<T>());
  const auto DopR((IDFT.row(0)               * DFT).real().template cast<T>());
  Dops = Mat(3, stp);
  for(int i = 0; i < Dops.cols(); i ++)
    Dops(0, i) = Dops(1, i) = Dops(2, i) = T(0);
  for(int i = 0; i < DopL.size(); i ++) {
    Dops(0, i)                                     = DopL[i];
    Dops(1, i - DopM.size() / 2 + Dops.cols() / 2) = DopM[i];
    Dops(2, i - DopR.size()     + Dops.cols()    ) = DopR[i];
  }
  return;
}

template <typename T> Eigen::Matrix<T, Eigen::Dynamic, 1> PseudoBump<T>::getPseudoBumpSub(const Vec& work, const Mat& cf) {
  cerr << "." << flush;
  Vec result(work.size());
  for(int s = 0; s < work.size(); s ++) {
    T sum(0);
    result[s] = T(0);
    for(int z = 0; z < cf.rows(); z ++) {
      // d/dt (local color) / ||local color||:
      Vec c(cf.cols());
      for(int u = 0; u < c.size(); u ++)
        c[u] = getImgPt(work, cf(z, u) + s);
      const auto buf(Dops * c);
      // N.B. <tangents, const distances> / <tangents, 1> is the result,
      //      this is quite pseudo because this similar to
      //      |tan(theta)| * d / |tan(theta)| / 1..
      const auto score(sqrt(buf.dot(buf) / c.dot(c)));
      if(isfinite(score)) {
        result[s] += score * pow(z / T(cf.rows()), T(2));
        sum       += score;
      }
    }
    result[s] /= sum;
  }
  return result;
}

template <typename T> Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> PseudoBump<T>::getPseudoBump(const Mat& in) {
  const auto cf(prepareLineAxis(sqrt(T(in.rows() * in.cols()))));
  Mat result(in.rows(), in.cols());
#if defined(_OPENMP)
#pragma omp parallel for schedule(static, 1)
#endif
  for(int i = 0; i < in.cols(); i ++)
    result.col(i)  = getPseudoBumpSub(in.col(i), cf);
#if defined(_OPENMP)
#pragma omp parallel for schedule(static, 1)
#endif
  for(int i = 0; i < in.rows(); i ++)
    result.row(i) += getPseudoBumpSub(in.row(i), cf);
  return result;
}

// get bump with multiple scale and vectorized result.
template <typename T> void PseudoBump<T>::getPseudoVec(const Mat& in, vector<Vec3>& geoms, vector<Veci3>& delaunay, const int& vbox, const T& rz) {
  assert(0 < vbox && T(0) < rz);
  // get vectorize.
  geoms = vector<Vec3>();
  T aavg(0);
  for(int i = 0; i < in.rows(); i ++)
    for(int j = 0; j < in.cols(); j ++)
      aavg += in(i, j);
  aavg /= in.rows() * in.cols();
  for(int i = 0; i < in.rows() / vbox + 1; i ++)
    for(int j = 0; j < in.cols() / vbox + 1; j ++) {
      if(in.rows() < (i + 1) * vbox ||
         in.cols() < (j + 1) * vbox) {
        if(geoms.size() >= 1) {
          Vec3 gbuf;
          gbuf[0] = i * vbox;
          gbuf[1] = j * vbox;
          gbuf[2] = geoms[geoms.size() - 1][2];
          geoms.push_back(gbuf);
        }
        continue;
      }
      T avg(0);
      for(int ii = i * vbox; ii < (i + 1) * vbox; ii ++)
        for(int jj = j * vbox; jj < (j + 1) * vbox; jj ++)
          avg += in(ii, jj);
      Vec3 work;
      work[0] = i * vbox;
      work[1] = j * vbox;
      const T intens(avg / vbox / vbox - aavg);
      work[2] = - intens * sqrt(T(in.rows() * in.cols())) * rz;
      geoms.push_back(work);
    }
  Vec3 avg;
  avg[0] = avg[1] = avg[2] = T(0);
  for(int i = 0; i < geoms.size(); i ++)
    avg += geoms[i];
  avg /= geoms.size();
  for(int i = 0; i < geoms.size(); i ++)
    geoms[i][2] -= avg[2];
  delaunay = vector<Veci3>();
  for(int i = 1; i < in.rows() / vbox + 1; i ++)
    for(int j = 0; j < in.cols() / vbox; j ++) {
      Veci3 work, work2;
      work[0]  = (i - 1) * (in.cols() / vbox + 1) + j;
      work[1]  =  i      * (in.cols() / vbox + 1) + j;
      work[2]  =  i      * (in.cols() / vbox + 1) + j + 1;
      work2[0] = (i - 1) * (in.cols() / vbox + 1) + j;
      work2[2] = (i - 1) * (in.cols() / vbox + 1) + j + 1;
      work2[1] =  i      * (in.cols() / vbox + 1) + j + 1;
      delaunay.push_back(work);
      delaunay.push_back(work2);
    }
  return;
}

template <typename T> Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> PseudoBump<T>::prepareLineAxis(const T& rstp) {
  Vec camera(2);
  camera[0] =   T(0);
  camera[1] = - T(1);

  Mat result(int(sqrt(rstp) * T(4)), Dops.cols());
  T   absmax(0);
#if defined(_OPENMP)
#pragma omp parallel for schedule(static, 1)
#endif
  for(int zi = 0; zi < result.rows(); zi ++)
    for(int s = 0; s < result.cols(); s ++) {
      Vec cpoint(2);
      cpoint[0] = s / T(result.cols() - 1) - 1 / T(2);
      // [1, rstp] works well and scaling works rapidly better.
      cpoint[1] = (T(1) - pow(zi / T(result.rows()), T(2))) * rstp * T(2);
      // x-z plane projection of point p with camera geometry c to z=0.
      // c := camera, p := cpoint.
      // <c + (p - c) * t, [0, 1]> = 0
      const T t(- camera[1] / (cpoint[1] - camera[1]));
      result(zi, s) = (camera + (cpoint - camera) * t)[0];
#if defined(_OPENMP)
#pragma omp atomic
#endif
      absmax = max(abs(result(zi, s)), absmax);
    }
  return result * rstp / absmax;
}

template <typename T> const T& PseudoBump<T>::getImgPt(const Vec& img, const T& y) {
  const int& h(img.size());
  const int  yy(abs((int(y + .5) + 3 * h) % (2 * h) - h) % h);
  return img[yy];
}

#define _2D3D_PSEUDO_
#endif

<|endoftext|>