<commit_before>#ifndef AL_OMNISTEREO_H
#define AL_OMNISTEREO_H

#include "allocore/math/al_Constants.hpp"
#include "allocore/graphics/al_Lens.hpp"
#include "allocore/graphics/al_Shader.hpp"
#include "allocore/graphics/al_Texture.hpp"

namespace al {

// Object to encapsulate rendering omni-stereo worlds via cube-maps:
class OmniStereo {
 public:
  // prefix this string to every vertex shader used in rendering the scene
  // use it as e.g.:
  // gl_Position = omni_cube(gl_ModelViewMatrix * gl_Vertex);
  // also be sure to call omni.uniforms(shader) in the OmniStereoDrawable
  // callback
  static std::string glsl() {
    return R"(
        // @omni_eye: the eye parallax distance.
        //  This will be zero for mono, and positive/negative for right/left
        // eyes.
        //  Pass this uniform to the shader in the OmniStereoDrawable
        // callback
        uniform float omni_eye;

        // @omni_radius: the radius of the allosphere in OpenGL units.
        //  This will be infinity for the original layout (we default to 1e10).
        uniform float omni_radius;

        // @omni_face: the GL_TEXTURE_CUBE_MAP face being rendered.
        //  For a typical forward-facing view, this should == 5.
        //  Pass this uniform to the shader in the OmniStereoDrawable
        // callback
        uniform int omni_face;

        // @omni_near: the near clipping plane.
        uniform float omni_near;

        // @omni_far: the far clipping plane.
        uniform float omni_far;

        // omni_render(vertex)
        // @vertex: the eye-space vertex to be rendered.
        //  Typically gl_Position = omni_render(gl_ModelViewMatrix *
        // gl_Vertex);
        vec4 omni_render(in vec4 vertex) {
          float l = length(vertex.xz);
          vec3 vn = normalize(vertex.xyz);
          // Precise formula.
          float displacement = omni_eye *
            (omni_radius * omni_radius -
               sqrt(l * l * omni_radius * omni_radius +
                    omni_eye * omni_eye * (omni_radius * omni_radius - l * l))) /
            (omni_radius * omni_radius - omni_eye * omni_eye);
          // Approximation, safe if omni_radius / omni_eye is very large, which is true for the allosphere.
          // float displacement = omni_eye * (1.0 - l / omni_radius);
          // Displace vertex.
          vertex.xz += vec2(displacement * vn.z, displacement * -vn.x);

          // convert eye-space into cubemap-space:
          // GL_TEXTURE_CUBE_MAP_POSITIVE_X
          if (omni_face == 0) {
            vertex.xyz = vec3(-vertex.z, -vertex.y, -vertex.x);
          }
              // GL_TEXTURE_CUBE_MAP_NEGATIVE_X
              else if (omni_face == 1) {
            vertex.xyz = vec3(vertex.z, -vertex.y, vertex.x);
          }
              // GL_TEXTURE_CUBE_MAP_POSITIVE_Y
              else if (omni_face == 2) {
            vertex.xyz = vec3(vertex.x, vertex.z, -vertex.y);
          }
              // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
              else if (omni_face == 3) {
            vertex.xyz = vec3(vertex.x, -vertex.z, vertex.y);
          }
              // GL_TEXTURE_CUBE_MAP_POSITIVE_Z
              else if (omni_face == 4) {
            vertex.xyz = vec3(vertex.x, -vertex.y, -vertex.z);
          }
              // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
              else {
            vertex.xyz = vec3(-vertex.x, -vertex.y, vertex.z);
          }
          // convert into screen-space:
          // simplified perspective projection since fovy = 90 and aspect = 1
          vertex.zw = vec2((vertex.z * (omni_far + omni_near) +
                            vertex.w * omni_far * omni_near * 2.) /
                               (omni_near - omni_far),
                           -vertex.z);
          return vertex;
        })";
  }

  ///  Abstract base class for any object that can be rendered via OmniStereo:
  class Drawable {
   public:
    /// Place drawing code here
    virtual void onDrawOmni(OmniStereo& omni) = 0;

    virtual ~Drawable() {}
  };

  /// Encapsulate the trio of fractional viewport, warp & blend maps:
  class Projection {
   public:
    struct Parameters {
      float projnum;        // ID of the projector
      float width, height;  // width/height in pixels
      Vec3f projector_position, screen_center, normal_unit, x_vec, y_vec;
      float screen_radius, bridge_radius, unused0;
    };

    Projection();

    void onCreate();

    // load warp/blend from disk:
    void readBlend(std::string path);
    void readWarp(std::string path);
    void readParameters(std::string path, bool verbose = true);
    void initParameters(bool verbose = true);

    // adjust the registration position:
    void registrationPosition(const Vec3d& pos);

    Texture& blend() { return mBlend; }
    Texture& warp() { return mWarp; }
    Viewport& viewport() { return mViewport; }

    void updatedWarp();

    Parameters params;

    // derived:
    Vec3f x_unit, y_unit;
    float x_pixel, y_pixel;
    float x_offset, y_offset;
    Vec3d position;

    // TODO: remove this
    int warpwidth, warpheight;

   protected:
    Texture mBlend, mWarp;
    Viewport mViewport;

    // the position/orientation of the raw map data relative to the real world
    Pose mRegistration;

    // the raw warp data:
    float* t;
    float* u;
    float* v;
  };

  /// Stereographic mode
  enum StereoMode {
    MONO = 0,
    SEQUENTIAL, /**< Alternate left/right eye frames */
    ACTIVE,     /**< Active quad-buffered stereo */
    DUAL,       /**< Dual side-by-side stereo */
    ANAGLYPH,   /**< Red (left eye) / cyan (right eye) stereo */
    LEFT_EYE,   /**< Left eye only */
    RIGHT_EYE   /**< Right eye only */
  };

  /// Anaglyph mode
  enum AnaglyphMode {
    RED_BLUE = 0, /**< */
    RED_GREEN,    /**< */
    RED_CYAN,     /**< */
    BLUE_RED,     /**< */
    GREEN_RED,    /**< */
    CYAN_RED      /**< */
  };

  enum WarpMode {
    FISHEYE,
    CYLINDER,
    RECT
  };

  enum BlendMode {
    NOBLEND,
    SOFTEDGE
  };

  // @resolution sets the resolution of the cube textures / render buffers:
  OmniStereo(unsigned resolution = 1024, bool useMipMaps = true);

  // @resolution should be a power of 2
  OmniStereo& resolution(unsigned resolution);
  unsigned resolution() { return mResolution; }

  // configure the projections according to files
  OmniStereo& configure(std::string configpath,
                        std::string configname = "default");

  // configure generatively:
  OmniStereo& configure(WarpMode wm, float aspect = 2., float fovy = M_PI);
  OmniStereo& configure(BlendMode bm);

  // capture a scene to the cubemap textures
  // this is likely to be an expensive call, as it will render the scene
  // six (twelve for stereo) times, by calling back into @draw
  // @draw should render without changing the viewport, modelview or projection
  // matrices
  // @lens is used for near/far clipping planes, and eye separation
  // @pose sets the camera position/orientation
  void capture(OmniStereo::Drawable& drawable, const Lens& lens,
               const Pose& pose);
  // render the captured scene to multiple warp maps and viewports
  // @viewport is the pixel dimensions of the window
  void draw(const Lens& lens, const Pose& pose, const Viewport& vp);

  // typically they would be combined like this:
  void onFrame(OmniStereo::Drawable& drawable, const Lens& lens,
               const Pose& pose, const Viewport& vp) {
    capture(drawable, lens, pose);
    draw(lens, pose, vp);
  }

  // render front-view only (bypass FBO)
  void onFrameFront(OmniStereo::Drawable& drawable, const Lens& lens,
                    const Pose& pose, const Viewport& vp);

  // send the proper uniforms to the shader:
  void uniforms(ShaderProgram& program) const;

  // enable/disable stereographic mode:
  OmniStereo& stereo(bool b) {
    mStereo = b;
    return *this;
  }
  bool stereo() const { return mStereo; }

  OmniStereo& mode(StereoMode m) {
    mMode = m;
    return *this;
  }
  StereoMode mode() { return mMode; }

  // returns true if configured for active stereo:
  bool activeStereo() { return mMode == ACTIVE; }

  // returns true if config file suggested fullscreen by default
  bool fullScreen() { return mFullScreen; }

  // get/set the background color
  Color& clearColor() { return mClearColor; }

  // get individual projector configurations:
  Projection& projection(int i) { return mProjections[i]; }
  int numProjections() const { return mNumProjections; }

  // useful accessors:
  GLuint texture() const { return mTex[0]; }
  GLuint textureLeft() const { return mTex[0]; }
  GLuint textureRight() const { return mTex[1]; }

  // the current face being rendered:
  int face() const { return mFace; }
  int currentEye() const { return mCurrentEye; }
  // the current eye parallax
  // (positive for right eye, negative for left, zero for mono):
  float eye() const { return mEyeParallax; }
  // the radius of the sphere in OpenGL units, default to 1e10, when we can ignore the effect.
  float sphereRadius() const { return mSphereRadius; }
  float sphereRadius(float value) { return mSphereRadius = value; }

  // create GPU resources:
  void onCreate();
  void onDestroy();

  // configure the warp maps
  void loadWarps(std::string calibrationpath, std::string hostname = "default");

  // debugging:
  void drawWarp(const Viewport& vp);
  void drawBlend(const Viewport& vp);
  void drawSphereMap(Texture& map, const Lens& lens, const Pose& pose,
                     const Viewport& vp);
  void drawDemo(const Lens& lens, const Pose& pose, const Viewport& vp);

  // adjust the registration position:
  void registrationPosition(const Vec3d& pos) {
    for (int i = 0; i < numProjections(); i++) {
      projection(i).registrationPosition(pos);
    }
  }

 protected:
  // supports up to 4 warps/viewports
  Projection mProjections[4];

  typedef void (OmniStereo::*DrawMethod)(const Pose& pose, double eye);
  void drawEye(const Pose& pose, double eye);
  void drawQuadEye(const Pose& pose, double eye);
  void drawDemoEye(const Pose& pose, double eye);

  template <DrawMethod F>
  void drawStereo(const Lens& lens, const Pose& pose, const Viewport& viewport);

  void drawQuad();

  void capture_eye(GLuint& tex, OmniStereo::Drawable& drawable);

  GLuint mTex[2];  // the cube map textures
  GLuint mFbo;
  GLuint mRbo;  // TODO: alternative depth cube-map texture option?
  ShaderProgram mCubeProgram, mSphereProgram, mWarpProgram, mDemoProgram;
  Mesh mQuad;

  Graphics gl;
  Matrix4d mModelView;
  Color mClearColor;

  // these become shader uniforms:
  int mFace, mCurrentEye;
  float mSphereRadius; // The radius of the sphere in OpenGL units.
  float mEyeParallax, mNear, mFar;

  unsigned mResolution;
  unsigned mNumProjections;
  int mFrame;

  StereoMode mMode;
  AnaglyphMode mAnaglyphMode;

  bool mStereo, mMipmap, mFullScreen;
};

/* inline implementation */

inline void OmniStereo::uniforms(ShaderProgram& program) const {
  program.uniform("omni_face", mFace);
  program.uniform("omni_eye", mEyeParallax);
  program.uniform("omni_near", mNear);
  program.uniform("omni_far", mFar);
  program.uniform("omni_radius", mSphereRadius);
  gl.error("sending OmniStereo uniforms");
}

template <OmniStereo::DrawMethod F>
inline void OmniStereo::drawStereo(const Lens& lens, const Pose& pose,
                                   const Viewport& vp) {
  double eye = lens.eyeSep();
  switch (mMode) {
    case SEQUENTIAL:
      if (mFrame & 1) {
        (this->*F)(pose, eye);
      } else {
        (this->*F)(pose, -eye);
      }
      break;

    case ACTIVE:
      glDrawBuffer(GL_BACK_RIGHT);
      gl.error("OmniStereo drawStereo GL_BACK_RIGHT");
      (this->*F)(pose, eye);

      glDrawBuffer(GL_BACK_LEFT);
      gl.error("OmniStereo drawStereo GL_BACK_LEFT");
      (this->*F)(pose, -eye);

      glDrawBuffer(GL_BACK);
      gl.error("OmniStereo drawStereo GL_BACK");
      break;

    case DUAL:
      gl.viewport(vp.l + vp.w * 0.5, vp.b, vp.w * 0.5, vp.h);
      (this->*F)(pose, eye);
      gl.viewport(vp.l, vp.b, vp.w * 0.5, vp.h);
      (this->*F)(pose, -eye);
      break;

    case ANAGLYPH:
      switch (mAnaglyphMode) {
        case RED_BLUE:
        case RED_GREEN:
        case RED_CYAN:
          glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
          break;
        case BLUE_RED:
          glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
          break;
        case GREEN_RED:
          glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
          break;
        case CYAN_RED:
          glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
          break;
        default:
          glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
      }
      (this->*F)(pose, eye);

      switch (mAnaglyphMode) {
        case RED_BLUE:
          glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
          break;
        case RED_GREEN:
          glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
          break;
        case RED_CYAN:
          glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
          break;
        case BLUE_RED:
        case GREEN_RED:
        case CYAN_RED:
          glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
          break;
        default:
          glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
      }
      // clear depth before this pass:
      gl.depthMask(1);
      gl.depthTesting(1);
      gl.clear(gl.DEPTH_BUFFER_BIT);
      (this->*F)(pose, -eye);

      break;

    case RIGHT_EYE:
      (this->*F)(pose, eye);
      break;

    case LEFT_EYE:
      (this->*F)(pose, -eye);
      break;

    case MONO:
    default:
      (this->*F)(pose, 0);
      break;
  }
}

}  // al::

#endif
<commit_msg>OmniStereo: getters for near & far<commit_after>#ifndef AL_OMNISTEREO_H
#define AL_OMNISTEREO_H

#include "allocore/math/al_Constants.hpp"
#include "allocore/graphics/al_Lens.hpp"
#include "allocore/graphics/al_Shader.hpp"
#include "allocore/graphics/al_Texture.hpp"

namespace al {

// Object to encapsulate rendering omni-stereo worlds via cube-maps:
class OmniStereo {
 public:
  // prefix this string to every vertex shader used in rendering the scene
  // use it as e.g.:
  // gl_Position = omni_cube(gl_ModelViewMatrix * gl_Vertex);
  // also be sure to call omni.uniforms(shader) in the OmniStereoDrawable
  // callback
  static std::string glsl() {
    return R"(
        // @omni_eye: the eye parallax distance.
        //  This will be zero for mono, and positive/negative for right/left
        // eyes.
        //  Pass this uniform to the shader in the OmniStereoDrawable
        // callback
        uniform float omni_eye;

        // @omni_radius: the radius of the allosphere in OpenGL units.
        //  This will be infinity for the original layout (we default to 1e10).
        uniform float omni_radius;

        // @omni_face: the GL_TEXTURE_CUBE_MAP face being rendered.
        //  For a typical forward-facing view, this should == 5.
        //  Pass this uniform to the shader in the OmniStereoDrawable
        // callback
        uniform int omni_face;

        // @omni_near: the near clipping plane.
        uniform float omni_near;

        // @omni_far: the far clipping plane.
        uniform float omni_far;

        // omni_render(vertex)
        // @vertex: the eye-space vertex to be rendered.
        //  Typically gl_Position = omni_render(gl_ModelViewMatrix *
        // gl_Vertex);
        vec4 omni_render(in vec4 vertex) {
          float l = length(vertex.xz);
          vec3 vn = normalize(vertex.xyz);
          // Precise formula.
          float displacement = omni_eye *
            (omni_radius * omni_radius -
               sqrt(l * l * omni_radius * omni_radius +
                    omni_eye * omni_eye * (omni_radius * omni_radius - l * l))) /
            (omni_radius * omni_radius - omni_eye * omni_eye);
          // Approximation, safe if omni_radius / omni_eye is very large, which is true for the allosphere.
          // float displacement = omni_eye * (1.0 - l / omni_radius);
          // Displace vertex.
          vertex.xz += vec2(displacement * vn.z, displacement * -vn.x);

          // convert eye-space into cubemap-space:
          // GL_TEXTURE_CUBE_MAP_POSITIVE_X
          if (omni_face == 0) {
            vertex.xyz = vec3(-vertex.z, -vertex.y, -vertex.x);
          }
              // GL_TEXTURE_CUBE_MAP_NEGATIVE_X
              else if (omni_face == 1) {
            vertex.xyz = vec3(vertex.z, -vertex.y, vertex.x);
          }
              // GL_TEXTURE_CUBE_MAP_POSITIVE_Y
              else if (omni_face == 2) {
            vertex.xyz = vec3(vertex.x, vertex.z, -vertex.y);
          }
              // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
              else if (omni_face == 3) {
            vertex.xyz = vec3(vertex.x, -vertex.z, vertex.y);
          }
              // GL_TEXTURE_CUBE_MAP_POSITIVE_Z
              else if (omni_face == 4) {
            vertex.xyz = vec3(vertex.x, -vertex.y, -vertex.z);
          }
              // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
              else {
            vertex.xyz = vec3(-vertex.x, -vertex.y, vertex.z);
          }
          // convert into screen-space:
          // simplified perspective projection since fovy = 90 and aspect = 1
          vertex.zw = vec2((vertex.z * (omni_far + omni_near) +
                            vertex.w * omni_far * omni_near * 2.) /
                               (omni_near - omni_far),
                           -vertex.z);
          return vertex;
        })";
  }

  ///  Abstract base class for any object that can be rendered via OmniStereo:
  class Drawable {
   public:
    /// Place drawing code here
    virtual void onDrawOmni(OmniStereo& omni) = 0;

    virtual ~Drawable() {}
  };

  /// Encapsulate the trio of fractional viewport, warp & blend maps:
  class Projection {
   public:
    struct Parameters {
      float projnum;        // ID of the projector
      float width, height;  // width/height in pixels
      Vec3f projector_position, screen_center, normal_unit, x_vec, y_vec;
      float screen_radius, bridge_radius, unused0;
    };

    Projection();

    void onCreate();

    // load warp/blend from disk:
    void readBlend(std::string path);
    void readWarp(std::string path);
    void readParameters(std::string path, bool verbose = true);
    void initParameters(bool verbose = true);

    // adjust the registration position:
    void registrationPosition(const Vec3d& pos);

    Texture& blend() { return mBlend; }
    Texture& warp() { return mWarp; }
    Viewport& viewport() { return mViewport; }

    void updatedWarp();

    Parameters params;

    // derived:
    Vec3f x_unit, y_unit;
    float x_pixel, y_pixel;
    float x_offset, y_offset;
    Vec3d position;

    // TODO: remove this
    int warpwidth, warpheight;

   protected:
    Texture mBlend, mWarp;
    Viewport mViewport;

    // the position/orientation of the raw map data relative to the real world
    Pose mRegistration;

    // the raw warp data:
    float* t;
    float* u;
    float* v;
  };

  /// Stereographic mode
  enum StereoMode {
    MONO = 0,
    SEQUENTIAL, /**< Alternate left/right eye frames */
    ACTIVE,     /**< Active quad-buffered stereo */
    DUAL,       /**< Dual side-by-side stereo */
    ANAGLYPH,   /**< Red (left eye) / cyan (right eye) stereo */
    LEFT_EYE,   /**< Left eye only */
    RIGHT_EYE   /**< Right eye only */
  };

  /// Anaglyph mode
  enum AnaglyphMode {
    RED_BLUE = 0, /**< */
    RED_GREEN,    /**< */
    RED_CYAN,     /**< */
    BLUE_RED,     /**< */
    GREEN_RED,    /**< */
    CYAN_RED      /**< */
  };

  enum WarpMode {
    FISHEYE,
    CYLINDER,
    RECT
  };

  enum BlendMode {
    NOBLEND,
    SOFTEDGE
  };

  // @resolution sets the resolution of the cube textures / render buffers:
  OmniStereo(unsigned resolution = 1024, bool useMipMaps = true);

  // @resolution should be a power of 2
  OmniStereo& resolution(unsigned resolution);
  unsigned resolution() { return mResolution; }

  // configure the projections according to files
  OmniStereo& configure(std::string configpath,
                        std::string configname = "default");

  // configure generatively:
  OmniStereo& configure(WarpMode wm, float aspect = 2., float fovy = M_PI);
  OmniStereo& configure(BlendMode bm);

  // capture a scene to the cubemap textures
  // this is likely to be an expensive call, as it will render the scene
  // six (twelve for stereo) times, by calling back into @draw
  // @draw should render without changing the viewport, modelview or projection
  // matrices
  // @lens is used for near/far clipping planes, and eye separation
  // @pose sets the camera position/orientation
  void capture(OmniStereo::Drawable& drawable, const Lens& lens,
               const Pose& pose);
  // render the captured scene to multiple warp maps and viewports
  // @viewport is the pixel dimensions of the window
  void draw(const Lens& lens, const Pose& pose, const Viewport& vp);

  // typically they would be combined like this:
  void onFrame(OmniStereo::Drawable& drawable, const Lens& lens,
               const Pose& pose, const Viewport& vp) {
    capture(drawable, lens, pose);
    draw(lens, pose, vp);
  }

  // render front-view only (bypass FBO)
  void onFrameFront(OmniStereo::Drawable& drawable, const Lens& lens,
                    const Pose& pose, const Viewport& vp);

  // send the proper uniforms to the shader:
  void uniforms(ShaderProgram& program) const;

  // enable/disable stereographic mode:
  OmniStereo& stereo(bool b) {
    mStereo = b;
    return *this;
  }
  bool stereo() const { return mStereo; }

  OmniStereo& mode(StereoMode m) {
    mMode = m;
    return *this;
  }
  StereoMode mode() { return mMode; }

  // returns true if configured for active stereo:
  bool activeStereo() { return mMode == ACTIVE; }

  // returns true if config file suggested fullscreen by default
  bool fullScreen() { return mFullScreen; }

  // get/set the background color
  Color& clearColor() { return mClearColor; }

  // get individual projector configurations:
  Projection& projection(int i) { return mProjections[i]; }
  int numProjections() const { return mNumProjections; }

  // useful accessors:
  GLuint texture() const { return mTex[0]; }
  GLuint textureLeft() const { return mTex[0]; }
  GLuint textureRight() const { return mTex[1]; }

  // the current face being rendered:
  int face() const { return mFace; }
  int currentEye() const { return mCurrentEye; }
  // the current eye parallax
  // (positive for right eye, negative for left, zero for mono):
  float eye() const { return mEyeParallax; }
  // the radius of the sphere in OpenGL units, default to 1e10, when we can ignore the effect.
  float sphereRadius() const { return mSphereRadius; }
  float sphereRadius(float value) { return mSphereRadius = value; }
  float near() const { return mNear; }
  float far() const { return mFar; }

  // create GPU resources:
  void onCreate();
  void onDestroy();

  // configure the warp maps
  void loadWarps(std::string calibrationpath, std::string hostname = "default");

  // debugging:
  void drawWarp(const Viewport& vp);
  void drawBlend(const Viewport& vp);
  void drawSphereMap(Texture& map, const Lens& lens, const Pose& pose,
                     const Viewport& vp);
  void drawDemo(const Lens& lens, const Pose& pose, const Viewport& vp);

  // adjust the registration position:
  void registrationPosition(const Vec3d& pos) {
    for (int i = 0; i < numProjections(); i++) {
      projection(i).registrationPosition(pos);
    }
  }

 protected:
  // supports up to 4 warps/viewports
  Projection mProjections[4];

  typedef void (OmniStereo::*DrawMethod)(const Pose& pose, double eye);
  void drawEye(const Pose& pose, double eye);
  void drawQuadEye(const Pose& pose, double eye);
  void drawDemoEye(const Pose& pose, double eye);

  template <DrawMethod F>
  void drawStereo(const Lens& lens, const Pose& pose, const Viewport& viewport);

  void drawQuad();

  void capture_eye(GLuint& tex, OmniStereo::Drawable& drawable);

  GLuint mTex[2];  // the cube map textures
  GLuint mFbo;
  GLuint mRbo;  // TODO: alternative depth cube-map texture option?
  ShaderProgram mCubeProgram, mSphereProgram, mWarpProgram, mDemoProgram;
  Mesh mQuad;

  Graphics gl;
  Matrix4d mModelView;
  Color mClearColor;

  // these become shader uniforms:
  int mFace, mCurrentEye;
  float mSphereRadius; // The radius of the sphere in OpenGL units.
  float mEyeParallax, mNear, mFar;

  unsigned mResolution;
  unsigned mNumProjections;
  int mFrame;

  StereoMode mMode;
  AnaglyphMode mAnaglyphMode;

  bool mStereo, mMipmap, mFullScreen;
};

/* inline implementation */

inline void OmniStereo::uniforms(ShaderProgram& program) const {
  program.uniform("omni_face", mFace);
  program.uniform("omni_eye", mEyeParallax);
  program.uniform("omni_near", mNear);
  program.uniform("omni_far", mFar);
  program.uniform("omni_radius", mSphereRadius);
  gl.error("sending OmniStereo uniforms");
}

template <OmniStereo::DrawMethod F>
inline void OmniStereo::drawStereo(const Lens& lens, const Pose& pose,
                                   const Viewport& vp) {
  double eye = lens.eyeSep();
  switch (mMode) {
    case SEQUENTIAL:
      if (mFrame & 1) {
        (this->*F)(pose, eye);
      } else {
        (this->*F)(pose, -eye);
      }
      break;

    case ACTIVE:
      glDrawBuffer(GL_BACK_RIGHT);
      gl.error("OmniStereo drawStereo GL_BACK_RIGHT");
      (this->*F)(pose, eye);

      glDrawBuffer(GL_BACK_LEFT);
      gl.error("OmniStereo drawStereo GL_BACK_LEFT");
      (this->*F)(pose, -eye);

      glDrawBuffer(GL_BACK);
      gl.error("OmniStereo drawStereo GL_BACK");
      break;

    case DUAL:
      gl.viewport(vp.l + vp.w * 0.5, vp.b, vp.w * 0.5, vp.h);
      (this->*F)(pose, eye);
      gl.viewport(vp.l, vp.b, vp.w * 0.5, vp.h);
      (this->*F)(pose, -eye);
      break;

    case ANAGLYPH:
      switch (mAnaglyphMode) {
        case RED_BLUE:
        case RED_GREEN:
        case RED_CYAN:
          glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
          break;
        case BLUE_RED:
          glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
          break;
        case GREEN_RED:
          glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
          break;
        case CYAN_RED:
          glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
          break;
        default:
          glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
      }
      (this->*F)(pose, eye);

      switch (mAnaglyphMode) {
        case RED_BLUE:
          glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
          break;
        case RED_GREEN:
          glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
          break;
        case RED_CYAN:
          glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
          break;
        case BLUE_RED:
        case GREEN_RED:
        case CYAN_RED:
          glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
          break;
        default:
          glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
      }
      // clear depth before this pass:
      gl.depthMask(1);
      gl.depthTesting(1);
      gl.clear(gl.DEPTH_BUFFER_BIT);
      (this->*F)(pose, -eye);

      break;

    case RIGHT_EYE:
      (this->*F)(pose, eye);
      break;

    case LEFT_EYE:
      (this->*F)(pose, -eye);
      break;

    case MONO:
    default:
      (this->*F)(pose, 0);
      break;
  }
}

}  // al::

#endif
<|endoftext|>


<commit_before>/* nuklear - 1.32.0 - public domain */

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <math.h>
#include <limits.h>
#include <time.h>
#include <errno.h>

#include <GL/glew.h>
#include <glfw3.h>

#include <stdbool.h>

#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_IMPLEMENTATION
#define NK_GLFW_GL3_IMPLEMENTATION
#include "nuklear.h"
#include "nuklear_glfw_gl3.h"

#define WINDOW_WIDTH 1200
#define WINDOW_HEIGHT 800

#define MAX_VERTEX_BUFFER 512 * 1024
#define MAX_ELEMENT_BUFFER 128 * 1024

#define UNUSED(a) (void)a
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) < (b) ? (b) : (a))
#define LEN(a) (sizeof(a)/sizeof(a)[0])

#define CL_USE_DEPRECATED_OPENCL_1_2_APIS

#ifdef __APPLE__
#include <OpenCL/opencl.h>
#else
#include <CL/cl.h>
#endif

#define MEM_SIZE (128)
#define MAX_SOURCE_SIZE (0x100000)

int test_opencl()
{
  cl_device_id device_id = NULL;
  cl_context context = NULL;
  cl_command_queue command_queue = NULL;
  cl_mem memobj = NULL;
  cl_program program = NULL;
  cl_kernel kernel = NULL;
  cl_platform_id platform_id = NULL;
  cl_uint ret_num_devices;
  cl_uint ret_num_platforms;
  cl_int ret;

  char string[MEM_SIZE];

  char cwd[1024];
  if (getcwd(cwd, sizeof(cwd)) != NULL) {
    fprintf(stdout, "Current working dir: %s\n", cwd);
  } else {
    // perror("getcwd() error");
    fprintf(stderr,"getcwd() failed!\n");
    return 0;
  }

  FILE *fp;
  // char fileName[] = "C:/dev/cpp/hello.cl";
  char fileName[] = "hello.cl";

  #if defined(_WIN32) || defined(WIN32)
  char pathSeparator[] = "\\";
  #elif defined(__unix__) || defined(linux) || defined(__APPLE__)
  char pathSeparator[] = "/";
  #endif

  char * fullPath = (char*)malloc(sizeof(char) * (strlen(cwd) + strlen(pathSeparator) + strlen(fileName) + 1));
  if(fullPath != NULL) {
    fullPath[0] = '\0';   // ensures the memory is an empty string
    strcat(fullPath, cwd);
    strcat(fullPath, pathSeparator);
    strcat(fullPath, fileName);
  } else {
    fprintf(stderr,"malloc failed!\n");
    return 0;
  }

  char *source_str;
  size_t source_size;

  fprintf(stdout, "Full path: %s\n", fullPath);

  /* Load the source code containing the kernel*/
  fp = fopen(fullPath, "r");
  if (!fp) {
    fprintf(stderr, "Failed to load kernel.\n");
    exit(1);
  }
  source_str = (char*)malloc(MAX_SOURCE_SIZE);
  source_size = fread(source_str, 1, MAX_SOURCE_SIZE, fp);
  fclose(fp);

  /* Get Platform and Device Info */
  ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms);
  ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_DEFAULT, 1, &device_id, &ret_num_devices);

  /* Create OpenCL context */
  context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret);

  /* Create Command Queue */
  command_queue = clCreateCommandQueue(context, device_id, 0, &ret);

  /* Create Memory Buffer */
  memobj = clCreateBuffer(context, CL_MEM_READ_WRITE,MEM_SIZE * sizeof(char), NULL, &ret);

  /* Create Kernel Program from the source */
  program = clCreateProgramWithSource(context, 1, (const char **)&source_str,
  (const size_t *)&source_size, &ret);

  /* Build Kernel Program */
  ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);

  /* Create OpenCL Kernel */
  kernel = clCreateKernel(program, "hello", &ret);

  /* Set OpenCL Kernel Parameters */
  ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&memobj);

  /* Execute OpenCL Kernel */
  ret = clEnqueueTask(command_queue, kernel, 0, NULL,NULL);

  /* Copy results from the memory buffer */
  ret = clEnqueueReadBuffer(command_queue, memobj, CL_TRUE, 0,
  MEM_SIZE * sizeof(char),string, 0, NULL, NULL);

  /* Display Result */
  puts(string);

  /* Finalization */
  ret = clFlush(command_queue);
  ret = clFinish(command_queue);
  ret = clReleaseKernel(kernel);
  ret = clReleaseProgram(program);
  ret = clReleaseMemObject(memobj);
  ret = clReleaseCommandQueue(command_queue);
  ret = clReleaseContext(context);

  free(source_str);

  return 0;
}

/* ===============================================================
 *
 *                          EXAMPLE
 *
 * ===============================================================*/
/* This are some code examples to provide a small overview of what can be
 * done with this library. To try out an example uncomment the include
 * and the corresponding function. */
/*#include "../style.c"*/
/*#include "../calculator.c"*/
/*#include "../overview.c"*/
/*#include "../node_editor.c"*/

/* ===============================================================
 *
 *                          DEMO
 *
 * ===============================================================*/
static void error_callback(int e, const char *d)
{printf("Error %d: %s\n", e, d);}

int main(void)
{
    test_opencl();

    /* Platform */
    static GLFWwindow *win;
    int width = 0, height = 0;
    struct nk_context *ctx;
    struct nk_color background;

    /* GLFW */
    glfwSetErrorCallback(error_callback);
    if (!glfwInit()) {
        fprintf(stdout, "[GFLW] failed to init!\n");
        exit(1);
    }
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
    win = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Demo", NULL, NULL);
    glfwMakeContextCurrent(win);
    glfwGetWindowSize(win, &width, &height);

    /* OpenGL */
    glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
    glewExperimental = 1;
    if (glewInit() != GLEW_OK) {
        fprintf(stderr, "Failed to setup GLEW\n");
        exit(1);
    }

    ctx = nk_glfw3_init(win, NK_GLFW3_INSTALL_CALLBACKS);
    /* Load Fonts: if none of these are loaded a default font will be used  */
    /* Load Cursor: if you uncomment cursor loading please hide the cursor */
    {struct nk_font_atlas *atlas;
    nk_glfw3_font_stash_begin(&atlas);
    /*struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "../../../extra_font/DroidSans.ttf", 14, 0);*/
    /*struct nk_font *roboto = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Roboto-Regular.ttf", 14, 0);*/
    /*struct nk_font *future = nk_font_atlas_add_from_file(atlas, "../../../extra_font/kenvector_future_thin.ttf", 13, 0);*/
    /*struct nk_font *clean = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyClean.ttf", 12, 0);*/
    /*struct nk_font *tiny = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyTiny.ttf", 10, 0);*/
    /*struct nk_font *cousine = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Cousine-Regular.ttf", 13, 0);*/
    nk_glfw3_font_stash_end();
    /*nk_style_load_all_cursors(ctx, atlas->cursors);*/
    /*nk_style_set_font(ctx, &droid->handle);*/}

    /* style.c */
    /*set_style(ctx, THEME_WHITE);*/
    /*set_style(ctx, THEME_RED);*/
    /*set_style(ctx, THEME_BLUE);*/
    /*set_style(ctx, THEME_DARK);*/

    bool show_text = false;

    background = nk_rgb(28,48,62);
    while (!glfwWindowShouldClose(win))
    {
        /* Input */
        glfwPollEvents();
        nk_glfw3_new_frame();

        /* GUI */
        if (nk_begin(ctx, "Demo", nk_rect(50, 50, 230, 250),
            NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
            NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
        {
            enum {EASY, HARD};
            static int op = EASY;
            static int property = 20;
            nk_layout_row_static(ctx, 30, 80, 1);
            if (nk_button_label(ctx, "button"))
                fprintf(stdout, "button pressed\n");

            nk_layout_row_dynamic(ctx, 30, 2);
            if (nk_option_label(ctx, "easy", op == EASY)) op = EASY;
            if (nk_option_label(ctx, "hard", op == HARD)) op = HARD;

            nk_layout_row_dynamic(ctx, 25, 1);
            nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1);

            nk_layout_row_dynamic(ctx, 20, 1);
            nk_label(ctx, "background:", NK_TEXT_LEFT);
            nk_layout_row_dynamic(ctx, 25, 1);
            if (nk_combo_begin_color(ctx, background, nk_vec2(nk_widget_width(ctx),400))) {
                nk_layout_row_dynamic(ctx, 120, 1);
                background = nk_color_picker(ctx, background, NK_RGBA);
                nk_layout_row_dynamic(ctx, 25, 1);
                background.r = (nk_byte)nk_propertyi(ctx, "#R:", 0, background.r, 255, 1,1);
                background.g = (nk_byte)nk_propertyi(ctx, "#G:", 0, background.g, 255, 1,1);
                background.b = (nk_byte)nk_propertyi(ctx, "#B:", 0, background.b, 255, 1,1);
                background.a = (nk_byte)nk_propertyi(ctx, "#A:", 0, background.a, 255, 1,1);
                nk_combo_end(ctx);
            }
        }
        nk_end(ctx);

        if (nk_begin(ctx, "Nuklear", nk_rect(WINDOW_WIDTH/2 - 110, WINDOW_HEIGHT/2 - 110, 220, 220),
                     NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE))
        {
            // Widgets code here
            nk_layout_row_dynamic(ctx, 20, 1);

            if (show_text == true) {
                nk_label(ctx, "Hello, world!", NK_TEXT_LEFT);
            } else {
                nk_label(ctx, "", NK_TEXT_LEFT);
            }

            if (nk_button_label(ctx, "Clear")) {
                show_text = false;
            }

            if (nk_button_label(ctx, "Hello, world!")) {
                show_text = true;
            }
        }
        nk_end(ctx);

        /* -------------- EXAMPLES ---------------- */
        /*calculator(ctx);*/
        /*overview(ctx);*/
        /*node_editor(ctx);*/
        /* ----------------------------------------- */

        /* Draw */
        {float bg[4];
        nk_color_fv(bg, background);
        glfwGetWindowSize(win, &width, &height);
        glViewport(0, 0, width, height);
        glClear(GL_COLOR_BUFFER_BIT);
        glClearColor(bg[0], bg[1], bg[2], bg[3]);
        /* IMPORTANT: `nk_glfw_render` modifies some global OpenGL state
         * with blending, scissor, face culling, depth test and viewport and
         * defaults everything back into a default state.
         * Make sure to either a.) save and restore or b.) reset your own state after
         * rendering the UI. */
        nk_glfw3_render(NK_ANTI_ALIASING_ON, MAX_VERTEX_BUFFER, MAX_ELEMENT_BUFFER);
        glfwSwapBuffers(win);}
    }
    nk_glfw3_shutdown();
    glfwTerminate();
    return 0;
}
<commit_msg>Add simple line<commit_after>/* nuklear - 1.32.0 - public domain */

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <math.h>
#include <limits.h>
#include <time.h>
#include <errno.h>

#include <GL/glew.h>
#include <glfw3.h>

#include <stdbool.h>

#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_IMPLEMENTATION
#define NK_GLFW_GL3_IMPLEMENTATION
#include "nuklear.h"
#include "nuklear_glfw_gl3.h"

#define WINDOW_WIDTH 1200
#define WINDOW_HEIGHT 800

#define MAX_VERTEX_BUFFER 512 * 1024
#define MAX_ELEMENT_BUFFER 128 * 1024

#define UNUSED(a) (void)a
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) < (b) ? (b) : (a))
#define LEN(a) (sizeof(a)/sizeof(a)[0])

#define CL_USE_DEPRECATED_OPENCL_1_2_APIS

#ifdef __APPLE__
#include <OpenCL/opencl.h>
#else
#include <CL/cl.h>
#endif

#define MEM_SIZE (128)
#define MAX_SOURCE_SIZE (0x100000)

int test_opencl()
{
  cl_device_id device_id = NULL;
  cl_context context = NULL;
  cl_command_queue command_queue = NULL;
  cl_mem memobj = NULL;
  cl_program program = NULL;
  cl_kernel kernel = NULL;
  cl_platform_id platform_id = NULL;
  cl_uint ret_num_devices;
  cl_uint ret_num_platforms;
  cl_int ret;

  char string[MEM_SIZE];

  char cwd[1024];
  if (getcwd(cwd, sizeof(cwd)) != NULL) {
    fprintf(stdout, "Current working dir: %s\n", cwd);
  } else {
    // perror("getcwd() error");
    fprintf(stderr,"getcwd() failed!\n");
    return 0;
  }

  FILE *fp;
  // char fileName[] = "C:/dev/cpp/hello.cl";
  char fileName[] = "hello.cl";

  #if defined(_WIN32) || defined(WIN32)
  char pathSeparator[] = "\\";
  #elif defined(__unix__) || defined(linux) || defined(__APPLE__)
  char pathSeparator[] = "/";
  #endif

  char * fullPath = (char*)malloc(sizeof(char) * (strlen(cwd) + strlen(pathSeparator) + strlen(fileName) + 1));
  if(fullPath != NULL) {
    fullPath[0] = '\0';   // ensures the memory is an empty string
    strcat(fullPath, cwd);
    strcat(fullPath, pathSeparator);
    strcat(fullPath, fileName);
  } else {
    fprintf(stderr,"malloc failed!\n");
    return 0;
  }

  char *source_str;
  size_t source_size;

  fprintf(stdout, "Full path: %s\n", fullPath);

  /* Load the source code containing the kernel*/
  fp = fopen(fullPath, "r");
  if (!fp) {
    fprintf(stderr, "Failed to load kernel.\n");
    exit(1);
  }
  source_str = (char*)malloc(MAX_SOURCE_SIZE);
  source_size = fread(source_str, 1, MAX_SOURCE_SIZE, fp);
  fclose(fp);

  /* Get Platform and Device Info */
  ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms);
  ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_DEFAULT, 1, &device_id, &ret_num_devices);

  /* Create OpenCL context */
  context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret);

  /* Create Command Queue */
  command_queue = clCreateCommandQueue(context, device_id, 0, &ret);

  /* Create Memory Buffer */
  memobj = clCreateBuffer(context, CL_MEM_READ_WRITE, MEM_SIZE * sizeof(char), NULL, &ret);

  /* Create Kernel Program from the source */
  program = clCreateProgramWithSource(
    context, 1, (const char **)&source_str, (const size_t *)&source_size, &ret
  );

  /* Build Kernel Program */
  ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);

  /* Create OpenCL Kernel */
  kernel = clCreateKernel(program, "hello", &ret);

  /* Set OpenCL Kernel Parameters */
  ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&memobj);

  /* Execute OpenCL Kernel */
  ret = clEnqueueTask(command_queue, kernel, 0, NULL,NULL);

  /* Copy results from the memory buffer */
  ret = clEnqueueReadBuffer(
    command_queue, memobj, CL_TRUE, 0, MEM_SIZE * sizeof(char), string, 0, NULL, NULL
  );

  /* Display Result */
  puts(string);

  /* Finalization */
  ret = clFlush(command_queue);
  ret = clFinish(command_queue);
  ret = clReleaseKernel(kernel);
  ret = clReleaseProgram(program);
  ret = clReleaseMemObject(memobj);
  ret = clReleaseCommandQueue(command_queue);
  ret = clReleaseContext(context);

  free(source_str);

  return 0;
}

/* ===============================================================
 *
 *                          EXAMPLE
 *
 * ===============================================================*/
/* This are some code examples to provide a small overview of what can be
 * done with this library. To try out an example uncomment the include
 * and the corresponding function. */
/*#include "../style.c"*/
/*#include "../calculator.c"*/
/*#include "../overview.c"*/
/*#include "../node_editor.c"*/

/* ===============================================================
 *
 *                          DEMO
 *
 * ===============================================================*/
static void error_callback(int e, const char *d)
{printf("Error %d: %s\n", e, d);}

int main(void)
{
    test_opencl();

    /* Platform */
    static GLFWwindow *win;
    int width = 0, height = 0;
    struct nk_context *ctx;
    struct nk_color background;

    /* GLFW */
    glfwSetErrorCallback(error_callback);
    if (!glfwInit()) {
        fprintf(stdout, "[GFLW] failed to init!\n");
        exit(1);
    }
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
    win = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Demo", NULL, NULL);
    glfwMakeContextCurrent(win);
    glfwGetWindowSize(win, &width, &height);

    /* OpenGL */
    glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
    glewExperimental = 1;
    if (glewInit() != GLEW_OK) {
        fprintf(stderr, "Failed to setup GLEW\n");
        exit(1);
    }

    ctx = nk_glfw3_init(win, NK_GLFW3_INSTALL_CALLBACKS);
    /* Load Fonts: if none of these are loaded a default font will be used  */
    /* Load Cursor: if you uncomment cursor loading please hide the cursor */
    {struct nk_font_atlas *atlas;
    nk_glfw3_font_stash_begin(&atlas);
    /*struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "../../../extra_font/DroidSans.ttf", 14, 0);*/
    /*struct nk_font *roboto = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Roboto-Regular.ttf", 14, 0);*/
    /*struct nk_font *future = nk_font_atlas_add_from_file(atlas, "../../../extra_font/kenvector_future_thin.ttf", 13, 0);*/
    /*struct nk_font *clean = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyClean.ttf", 12, 0);*/
    /*struct nk_font *tiny = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyTiny.ttf", 10, 0);*/
    /*struct nk_font *cousine = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Cousine-Regular.ttf", 13, 0);*/
    nk_glfw3_font_stash_end();
    /*nk_style_load_all_cursors(ctx, atlas->cursors);*/
    /*nk_style_set_font(ctx, &droid->handle);*/}

    /* style.c */
    /*set_style(ctx, THEME_WHITE);*/
    /*set_style(ctx, THEME_RED);*/
    /*set_style(ctx, THEME_BLUE);*/
    /*set_style(ctx, THEME_DARK);*/

    bool show_text = false;

    struct nk_command_buffer *canvas;
    const struct nk_color grid_color = nk_rgb(255, 255, 255);

    background = nk_rgb(28,48,62);
    while (!glfwWindowShouldClose(win))
    {
        /* Input */
        glfwPollEvents();
        nk_glfw3_new_frame();

        /* GUI */
        if (nk_begin(ctx, "Demo", nk_rect(50, 50, 230, 250),
            NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
            NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
        {
            enum {EASY, HARD};
            static int op = EASY;
            static int property = 20;
            nk_layout_row_static(ctx, 30, 80, 1);
            if (nk_button_label(ctx, "button"))
                fprintf(stdout, "button pressed\n");

            nk_layout_row_dynamic(ctx, 30, 2);
            if (nk_option_label(ctx, "easy", op == EASY)) op = EASY;
            if (nk_option_label(ctx, "hard", op == HARD)) op = HARD;

            nk_layout_row_dynamic(ctx, 25, 1);
            nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1);

            nk_layout_row_dynamic(ctx, 20, 1);
            nk_label(ctx, "background:", NK_TEXT_LEFT);
            nk_layout_row_dynamic(ctx, 25, 1);
            if (nk_combo_begin_color(ctx, background, nk_vec2(nk_widget_width(ctx),400))) {
                nk_layout_row_dynamic(ctx, 120, 1);
                background = nk_color_picker(ctx, background, NK_RGBA);
                nk_layout_row_dynamic(ctx, 25, 1);
                background.r = (nk_byte)nk_propertyi(ctx, "#R:", 0, background.r, 255, 1,1);
                background.g = (nk_byte)nk_propertyi(ctx, "#G:", 0, background.g, 255, 1,1);
                background.b = (nk_byte)nk_propertyi(ctx, "#B:", 0, background.b, 255, 1,1);
                background.a = (nk_byte)nk_propertyi(ctx, "#A:", 0, background.a, 255, 1,1);
                nk_combo_end(ctx);
            }
        }
        nk_end(ctx);

        if (nk_begin(ctx, "Nuklear", nk_rect(WINDOW_WIDTH/2 - 110, WINDOW_HEIGHT/2 - 110, 220, 220),
                     NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE))
        {
            // Widgets code here
            nk_layout_row_dynamic(ctx, 20, 1);

            if (show_text == true) {
                nk_label(ctx, "Hello, world!", NK_TEXT_LEFT);
            } else {
                nk_label(ctx, "", NK_TEXT_LEFT);
            }

            if (nk_button_label(ctx, "Clear")) {
                show_text = false;
            }

            if (nk_button_label(ctx, "Hello, world!")) {
                show_text = true;
            }

            canvas = nk_window_get_canvas(ctx);
            nk_stroke_line(canvas, 10, 10, 30, 30, 1.0f, grid_color);
        }
        nk_end(ctx);

        /* -------------- EXAMPLES ---------------- */
        /*calculator(ctx);*/
        /*overview(ctx);*/
        /*node_editor(ctx);*/
        /* ----------------------------------------- */

        /* Draw */
        {float bg[4];
        nk_color_fv(bg, background);
        glfwGetWindowSize(win, &width, &height);
        glViewport(0, 0, width, height);
        glClear(GL_COLOR_BUFFER_BIT);
        glClearColor(bg[0], bg[1], bg[2], bg[3]);
        /* IMPORTANT: `nk_glfw_render` modifies some global OpenGL state
         * with blending, scissor, face culling, depth test and viewport and
         * defaults everything back into a default state.
         * Make sure to either a.) save and restore or b.) reset your own state after
         * rendering the UI. */
        nk_glfw3_render(NK_ANTI_ALIASING_ON, MAX_VERTEX_BUFFER, MAX_ELEMENT_BUFFER);
        glfwSwapBuffers(win);}
    }
    nk_glfw3_shutdown();
    glfwTerminate();
    return 0;
}
<|endoftext|>


<commit_before>#include <MeshPaintComponent.hpp>

#include <iostream>

#include <Core/Mesh/TriangleMesh.hpp>
#include <Core/Mesh/MeshUtils.hpp>
#include <Core/Tasks/TaskQueue.hpp>

#include <Engine/Entity/Entity.hpp>
#include <Engine/Renderer/Mesh/Mesh.hpp>
#include <Engine/Renderer/RenderObject/RenderObject.hpp>
#include <Engine/Renderer/RenderObject/RenderObjectManager.hpp>
#include <Engine/Renderer/Material/Material.hpp>
#include <Engine/Renderer/RenderTechnique/RenderTechnique.hpp>
#include <Engine/Renderer/RenderTechnique/ShaderConfigFactory.hpp>

namespace MeshPaintPlugin {

MeshPaintComponent::MeshPaintComponent( const std::string& name ) :
    Ra::Engine::Component( name )
{}

MeshPaintComponent::~MeshPaintComponent() { }

void MeshPaintComponent::addTasks( Ra::Core::TaskQueue* taskQueue, const Ra::Engine::FrameInfo& info )
{
}

void MeshPaintComponent::setDataId( const std::string &id )
{
    m_dataId = id;
}

void MeshPaintComponent::initialize()
{
    auto compMess = Ra::Engine::ComponentMessenger::getInstance();
    //Look for the data we need
    bool geometryData = compMess->canGet< Ra::Core::TriangleMesh >( getEntity(), m_dataId );

    if( !geometryData )
    {
        LOG(logWARNING) << "Cannot initialize MeshPaint Component: no geometry data." << std::endl;
        return;
    }

    m_renderObjectReader = compMess->getterCallback< Ra::Core::Index >( getEntity(), m_dataId );

    auto ro = getRoMgr()->getRenderObject( *m_renderObjectReader() );
    m_baseConfig = ro->getRenderTechnique()->getConfiguration();
    m_baseColors = ro->getMesh()->getData( Ra::Engine::Mesh::VERTEX_COLOR );
    m_paintColors.resize( ro->getMesh()->getGeometry().m_vertices.size(), Ra::Core::Colors::Skin() );
    ro->getMesh()->addData( Ra::Engine::Mesh::VERTEX_COLOR, m_paintColors );
}

void MeshPaintComponent::startPaint( bool on )
{
    auto ro = getRoMgr()->getRenderObject( *m_renderObjectReader() );
    if (on)
    {
        ro->getRenderTechnique()->setConfiguration( Ra::Engine::ShaderConfigurationFactory::getConfiguration( "Plain" ) );
        ro->getMesh()->addData( Ra::Engine::Mesh::VERTEX_COLOR, m_paintColors );
    }
    else
    {
        ro->getRenderTechnique()->setConfiguration( m_baseConfig );
        ro->getMesh()->addData( Ra::Engine::Mesh::VERTEX_COLOR, m_baseColors );
    }
}

void MeshPaintComponent::paintMesh( const Ra::Engine::Renderer::PickingResult& picking, const Ra::Core::Color &color )
{
    // check it's for us
    if ( *m_renderObjectReader() != picking.m_roIdx || picking.m_mode == Ra::Engine::Renderer::RO )
    {
        return;
    }

    auto ro = getRoMgr()->getRenderObject( *m_renderObjectReader() );
    if ( ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_POINTS &&
         (picking.m_mode != Ra::Engine::Renderer::VERTEX &&
          picking.m_mode != Ra::Engine::Renderer::C_VERTEX) )
    {
        return;
    }

    if ( (ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_LINES ||
          ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_LINE_LOOP ||
          ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_LINE_STRIP ||
          ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_LINES_ADJACENCY ||
          ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_LINE_STRIP_ADJACENCY ||
          ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_TRIANGLES ||
          ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_TRIANGLE_STRIP ||
          ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_TRIANGLE_FAN ) )
    {
        // not supported yet -> might use same util functions as MeshFeatureTrackingComponent
        return;
    }

    const auto& T = ro->getMesh()->getGeometry().m_triangles;
    auto colors = ro->getMesh()->getData( Ra::Engine::Mesh::VERTEX_COLOR );

    switch (picking.m_mode)
    {
    case Ra::Engine::Renderer::VERTEX:
    case Ra::Engine::Renderer::C_VERTEX:
    {
        if ( ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_POINTS )
        {
            for (int t : picking.m_elementIdx)
            {
                colors[t] = color;
            }
        }
        else
        {
            for (int t = 0; t < picking.m_elementIdx.size(); ++t)
            {
                int v = T[ picking.m_elementIdx[t] ]( picking.m_vertexIdx[t] );
                colors[v] = color;
            }
        }
        break;
    }
    case Ra::Engine::Renderer::EDGE:
    case Ra::Engine::Renderer::C_EDGE:
    {
        for (int t = 0; t < picking.m_elementIdx.size(); ++t)
        {
            int v1 = T[ picking.m_elementIdx[t] ]( (picking.m_edgeIdx[t]+1)%3 );
            int v2 = T[ picking.m_elementIdx[t] ]( (picking.m_edgeIdx[t]+2)%3 );
            colors[v1] = colors[v2] = color;
        }
        break;
    }
    case Ra::Engine::Renderer::TRIANGLE:
    case Ra::Engine::Renderer::C_TRIANGLE:
    {
        for (int t = 0; t < picking.m_elementIdx.size(); ++t)
        {
            int v1 = T[ picking.m_elementIdx[t] ]( 0 );
            int v2 = T[ picking.m_elementIdx[t] ]( 1 );
            int v3 = T[ picking.m_elementIdx[t] ]( 2 );
            colors[v1] = colors[v2] = colors[v3] = color;
        }
        break;
    }
    default: break;
    }

    ro->getMesh()->addData( Ra::Engine::Mesh::VERTEX_COLOR, colors );
}

} // namespace MeshPaintPlugin

<commit_msg>Fix Paint on Triangle Meshes ;<commit_after>#include <MeshPaintComponent.hpp>

#include <iostream>

#include <Core/Mesh/TriangleMesh.hpp>
#include <Core/Mesh/MeshUtils.hpp>
#include <Core/Tasks/TaskQueue.hpp>

#include <Engine/Entity/Entity.hpp>
#include <Engine/Renderer/Mesh/Mesh.hpp>
#include <Engine/Renderer/RenderObject/RenderObject.hpp>
#include <Engine/Renderer/RenderObject/RenderObjectManager.hpp>
#include <Engine/Renderer/Material/Material.hpp>
#include <Engine/Renderer/RenderTechnique/RenderTechnique.hpp>
#include <Engine/Renderer/RenderTechnique/ShaderConfigFactory.hpp>

namespace MeshPaintPlugin {

MeshPaintComponent::MeshPaintComponent( const std::string& name ) :
    Ra::Engine::Component( name )
{}

MeshPaintComponent::~MeshPaintComponent() { }

void MeshPaintComponent::addTasks( Ra::Core::TaskQueue* taskQueue, const Ra::Engine::FrameInfo& info )
{
}

void MeshPaintComponent::setDataId( const std::string &id )
{
    m_dataId = id;
}

void MeshPaintComponent::initialize()
{
    auto compMess = Ra::Engine::ComponentMessenger::getInstance();
    //Look for the data we need
    bool geometryData = compMess->canGet< Ra::Core::TriangleMesh >( getEntity(), m_dataId );

    if( !geometryData )
    {
        LOG(logWARNING) << "Cannot initialize MeshPaint Component: no geometry data." << std::endl;
        return;
    }

    m_renderObjectReader = compMess->getterCallback< Ra::Core::Index >( getEntity(), m_dataId );

    auto ro = getRoMgr()->getRenderObject( *m_renderObjectReader() );
    m_baseConfig = ro->getRenderTechnique()->getConfiguration();
    m_baseColors = ro->getMesh()->getData( Ra::Engine::Mesh::VERTEX_COLOR );
    m_paintColors.resize( ro->getMesh()->getGeometry().m_vertices.size(), Ra::Core::Colors::Skin() );
    ro->getMesh()->addData( Ra::Engine::Mesh::VERTEX_COLOR, m_paintColors );
}

void MeshPaintComponent::startPaint( bool on )
{
    auto ro = getRoMgr()->getRenderObject( *m_renderObjectReader() );
    if (on)
    {
        ro->getRenderTechnique()->setConfiguration( Ra::Engine::ShaderConfigurationFactory::getConfiguration( "Plain" ) );
        ro->getMesh()->addData( Ra::Engine::Mesh::VERTEX_COLOR, m_paintColors );
    }
    else
    {
        ro->getRenderTechnique()->setConfiguration( m_baseConfig );
        ro->getMesh()->addData( Ra::Engine::Mesh::VERTEX_COLOR, m_baseColors );
    }
}

void MeshPaintComponent::paintMesh( const Ra::Engine::Renderer::PickingResult& picking, const Ra::Core::Color &color )
{
    // check it's for us
    if ( *m_renderObjectReader() != picking.m_roIdx || picking.m_mode == Ra::Engine::Renderer::RO )
    {
        return;
    }

    auto ro = getRoMgr()->getRenderObject( *m_renderObjectReader() );
    if ( ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_POINTS &&
         (picking.m_mode != Ra::Engine::Renderer::VERTEX &&
          picking.m_mode != Ra::Engine::Renderer::C_VERTEX) )
    {
        return;
    }

    if ( (ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_LINES ||
          ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_LINE_LOOP ||
          ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_LINE_STRIP ||
          ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_LINES_ADJACENCY ||
          ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_LINE_STRIP_ADJACENCY ||
          ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_TRIANGLE_STRIP ||
          ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_TRIANGLE_FAN ) )
    {
        // not supported yet -> might use same util functions as MeshFeatureTrackingComponent
        return;
    }

    const auto& T = ro->getMesh()->getGeometry().m_triangles;
    auto colors = ro->getMesh()->getData( Ra::Engine::Mesh::VERTEX_COLOR );

    switch (picking.m_mode)
    {
    case Ra::Engine::Renderer::VERTEX:
    case Ra::Engine::Renderer::C_VERTEX:
    {
        if ( ro->getMesh()->getRenderMode() == Ra::Engine::Mesh::RM_POINTS )
        {
            for (int t : picking.m_elementIdx)
            {
                colors[t] = color;
            }
        }
        else
        {
            for (int t = 0; t < picking.m_elementIdx.size(); ++t)
            {
                int v = T[ picking.m_elementIdx[t] ]( picking.m_vertexIdx[t] );
                colors[v] = color;
            }
        }
        break;
    }
    case Ra::Engine::Renderer::EDGE:
    case Ra::Engine::Renderer::C_EDGE:
    {
        for (int t = 0; t < picking.m_elementIdx.size(); ++t)
        {
            int v1 = T[ picking.m_elementIdx[t] ]( (picking.m_edgeIdx[t]+1)%3 );
            int v2 = T[ picking.m_elementIdx[t] ]( (picking.m_edgeIdx[t]+2)%3 );
            colors[v1] = colors[v2] = color;
        }
        break;
    }
    case Ra::Engine::Renderer::TRIANGLE:
    case Ra::Engine::Renderer::C_TRIANGLE:
    {
        for (int t = 0; t < picking.m_elementIdx.size(); ++t)
        {
            int v1 = T[ picking.m_elementIdx[t] ]( 0 );
            int v2 = T[ picking.m_elementIdx[t] ]( 1 );
            int v3 = T[ picking.m_elementIdx[t] ]( 2 );
            colors[v1] = colors[v2] = colors[v3] = color;
        }
        break;
    }
    default: break;
    }

    ro->getMesh()->addData( Ra::Engine::Mesh::VERTEX_COLOR, colors );
}

} // namespace MeshPaintPlugin

<|endoftext|>


<commit_before>#include "KAI/KAI.h"

#include <iostream>
#include <strstream>
#include <stdarg.h>

#include "KAI/Translator/Lexer.h"

using namespace std;

KAI_BEGIN

Lexer::Lexer(const char *in)
	: input(in)
{
	CreateLines();
	AddKeywords();
	Run();
}

void Lexer::AddKeywords()
{
	keyWords["if"] = Token::If;
	keyWords["else"] = Token::Else;
	keyWords["for"] = Token::For;
	keyWords["true"] = Token::True;
	keyWords["false"] = Token::False;
	keyWords["return"] = Token::Return;
	keyWords["self"] = Token::Self;
	keyWords["fun"] = Token::Fun;
	keyWords["yield"] = Token::Yield;
	keyWords["in"] = Token::In;
	keyWords["while"] = Token::While;
	keyWords["assert"] = Token::Assert;
}

bool Lexer::Run()
{
	offset = 0;
	lineNumber = 0;

	while (!Failed && NextToken())
		;

	return Add(Token::None, 0);
}

void Lexer::Print() const
{
	for (auto tok : tokens)
		std::cout << tok << " ";

	std::cout << std::endl;
}

Slice Lexer::Gather(int (*filt)(int))
{
	int start = offset;
	while (filt(Next()))
		;

	return Slice(start, offset);
}

bool Lexer::Add(Token::Type type, Slice slice)
{
	tokens.push_back(Token(type, *this, lineNumber, slice));
	return true;
}

bool Lexer::Add(Token::Type type, int len)
{
	Add(type, Slice(offset, offset + len));
	while (len--)
		Next();

	return true;
}

bool Lexer::LexAlpha()
{
	Token tok(Token::Ident, *this, lineNumber, Gather(isalnum));

	auto kw = keyWords.find(tok.Text());
	if (kw != keyWords.end())
		tok.type = kw->second;

	tokens.push_back(tok);

	return true;
}

int IsSpaceChar(int ch)
{
	return ch == ' ';
}

bool Lexer::NextToken()
{
	auto current = Current();
	if (current == 0)
		return false;

	if (isalpha(current))
		return LexAlpha();

	if (isdigit(current))
		return Add(Token::Int, Gather(isdigit));

	switch (current)
	{
	case '\t': return Add(Token::Tab);
	case '\n': return Add(Token::NewLine);
	case ';': return Add(Token::Semi);
	case '{': return Add(Token::OpenBrace);
	case '}': return Add(Token::CloseBrace);
	case '(': return Add(Token::OpenParan);
	case ')': return Add(Token::CloseParan);
	case ':': return Add(Token::Colon);
	case ' ': return Add(Token::Whitespace, Gather(IsSpaceChar));
	case '@': return Add(Token::Lookup);
	case ',': return Add(Token::Comma);
	case '*': return Add(Token::Mul);
	case '[': return Add(Token::OpenSquareBracket);
	case ']': return Add(Token::CloseSquareBracket);
	case '=': return AddIfNext('=', Token::Equiv, Token::Assign);
	case '!': return AddIfNext('=', Token::NotEquiv, Token::Not);
	case '&': return AddIfNext('&', Token::And, Token::BitAnd);
	case '|': return AddIfNext('|', Token::Or, Token::BitOr);
	case '<': return AddIfNext('=', Token::LessEquiv, Token::Less);
	case '>': return AddIfNext('=', Token::GreaterEquiv, Token::Greater);
	case '"': return LexString();
	case '\'': return LexAlpha();
	case '-':
		if (Peek() == '-')
		{
			Next();
			return Add(Token::Decrement);
		}
		if (Peek() == '=')
		{
			Next();
			return Add(Token::MinusAssign);
		}
		return Add(Token::Minus);

	case '.':
		if (Peek() == '.')
		{
			Next();
			if (Peek() == '.')
			{
				Next();
				return Add(Token::Replace, 3);
			}
			return Fail("Two dots");
		}
		return Add(Token::Dot);

	case '+':
		if (Peek() == '+')
		{
			Next();
			return Add(Token::Increment);
		}
		if (Peek() == '=')
		{
			Next();
			return Add(Token::PlusAssign);
		}
		return Add(Token::Plus);

	case '/':
		if (Peek() == '/')
		{
			Next();
			int start = offset;
			while (Next() != '\n')
				;
			return Add(Token::Comment, offset - start);
		}
		return Add(Token::Divide);
	}

	LexError("Unrecognised %c");

	return false;
}

std::string Lexer::CreateError(Token tok, const char *fmt, ...)
{
	char buff0[2000];
	va_list ap;
	va_start(ap, fmt);
	vsprintf_s(buff0, fmt, ap);

	const char *fmt1 = "%s(%d):[%d]: %s\n";
	char buff[2000];
	sprintf_s(buff, fmt1, "", tok.lineNumber, tok.slice.Start, buff0);
	int beforeContext = 1;
	int afterContext = 0;

	const Lexer &lex = *tok.lexer;
	int start = std::max(0, tok.lineNumber - beforeContext);
	int end = std::min((int)lex.lines.size() - 1, tok.lineNumber + afterContext);

	strstream err;
	err << buff << endl;
	for (int n = start; n <= end; ++n)
	{
		for (auto ch : lex.lines[n])
		{
			if (ch == '\t')
				err << "    ";
			else
				err << ch;
		}

		if (n == tok.lineNumber)
		{
			for (int ch = 0; ch < (int)lex.lines[n].size(); ++ch)
			{
				if (lex.lines[tok.lineNumber][ch] == '\t')
					err << "    ";
				else if (ch == tok.slice.Start)
				{
					err << '^';
					break;
				}
			}

			err << endl;
		}
	}

	err << ends;

	return err.str();
}

bool Process::Fail(const std::string &err)
{
	Failed = true;
	Error = err;

	return false;
}

bool Process::Fail(const char *fmt, ...)
{
	va_list ap;
	va_start(ap, fmt);
	char buffer[1000];
	vsprintf_s(buffer, fmt, ap);
	return Fail(std::string(buffer));
}

char Lexer::Current() const
{
	if (lineNumber == (int)lines.size())
		return 0;

	return Line()[offset];
}

const std::string &Lexer::Line() const
{
	return lines[lineNumber];
}

char Lexer::Next()
{
	if (EndOfLine())
	{
		offset = 0;
		++lineNumber;
	}
	else
		++offset;

	if (lineNumber == (int)lines.size())
		return 0;

	return Line()[offset];
}

char Lexer::Peek() const
{
	if (EndOfLine())
		return 0;

	return Line()[offset + 1];
}

void Lexer::CreateLines()
{
	// ensure we end with a newline.
	input.push_back('\n');

	size_t lineStart = 0;
	for (size_t n = 0; n < input.size(); ++n)
	{
		if (input[n] == '\n')
		{
			lines.push_back(input.substr(lineStart, n - lineStart + 1));
			lineStart = n + 1;
		}
	}
}

bool Lexer::EndOfLine() const
{
	return offset == (int)Line().size() - 1;
}

bool Lexer::AddIfNext(char ch, Token::Type thenType, Token::Type elseType)
{
	if (Peek() == ch)
	{
		Next();
		return Add(thenType, 2);
	}

	return Add(elseType, 1);
}

bool Lexer::AddTwoCharOp(Token::Type ty)
{
	Add(ty, 2);
	Next();

	return true;
}

bool Lexer::LexString()
{
	int start = offset;
	Next();
	while (!Failed && Current() != '"')
	{
		if (Current() == '\\')
		{
			switch (Next())
			{
			case '"':
			case 'n':
			case 't':
				break;

			default:
				LexError("Bad escape sequence %c");
				return false;
			}
		}

		if (Peek() == 0)
		{
			Fail("Bad string literal");
			return false;
		}

		Next();
	}

	Next();

	// the +1 and -1 to remove the start and end double quote characters
	tokens.push_back(Token(Token::String, *this, lineNumber, Slice(start + 1, offset - 1)));
	return true;
}

void Lexer::LexError(const char *text)
{
	Fail(CreateError(Token(Token::None, *this, lineNumber, Slice(offset, offset)), text, Current()));
}

KAI_END

<commit_msg>Re-ordered headers.<commit_after>#include <iostream>
#include <strstream>
#include <stdarg.h>

#include "KAI/KAI.h"
#include "KAI/Translator/Lexer.h"

using namespace std;

KAI_BEGIN

Lexer::Lexer(const char *in)
	: input(in)
{
	CreateLines();
	AddKeywords();
	Run();
}

void Lexer::AddKeywords()
{
	keyWords["if"] = Token::If;
	keyWords["else"] = Token::Else;
	keyWords["for"] = Token::For;
	keyWords["true"] = Token::True;
	keyWords["false"] = Token::False;
	keyWords["return"] = Token::Return;
	keyWords["self"] = Token::Self;
	keyWords["fun"] = Token::Fun;
	keyWords["yield"] = Token::Yield;
	keyWords["in"] = Token::In;
	keyWords["while"] = Token::While;
	keyWords["assert"] = Token::Assert;
}

bool Lexer::Run()
{
	offset = 0;
	lineNumber = 0;

	while (!Failed && NextToken())
		;

	return Add(Token::None, 0);
}

void Lexer::Print() const
{
	//std::copy(tokens.begin(), tokens.end(), ostream_iterator<Token>(std::cout, " "));
	for (auto tok : tokens)
		std::cout << tok << " ";

	std::cout << std::endl;
}

Slice Lexer::Gather(int (*filt)(int))
{
	int start = offset;
	while (filt(Next()))
		;

	return Slice(start, offset);
}

bool Lexer::Add(Token::Type type, Slice slice)
{
	tokens.push_back(Token(type, *this, lineNumber, slice));
	return true;
}

bool Lexer::Add(Token::Type type, int len)
{
	Add(type, Slice(offset, offset + len));
	while (len--)
		Next();

	return true;
}

bool Lexer::LexAlpha()
{
	Token tok(Token::Ident, *this, lineNumber, Gather(isalnum));

	auto kw = keyWords.find(tok.Text());
	if (kw != keyWords.end())
		tok.type = kw->second;

	tokens.push_back(tok);

	return true;
}

int IsSpaceChar(int ch)
{
	return ch == ' ';
}

bool Lexer::NextToken()
{
	auto current = Current();
	if (current == 0)
		return false;

	if (isalpha(current))
		return LexAlpha();

	if (isdigit(current))
		return Add(Token::Int, Gather(isdigit));

	switch (current)
	{
	case '\t': return Add(Token::Tab);
	case '\n': return Add(Token::NewLine);
	case ';': return Add(Token::Semi);
	case '{': return Add(Token::OpenBrace);
	case '}': return Add(Token::CloseBrace);
	case '(': return Add(Token::OpenParan);
	case ')': return Add(Token::CloseParan);
	case ':': return Add(Token::Colon);
	case ' ': return Add(Token::Whitespace, Gather(IsSpaceChar));
	case '@': return Add(Token::Lookup);
	case ',': return Add(Token::Comma);
	case '*': return Add(Token::Mul);
	case '[': return Add(Token::OpenSquareBracket);
	case ']': return Add(Token::CloseSquareBracket);
	case '=': return AddIfNext('=', Token::Equiv, Token::Assign);
	case '!': return AddIfNext('=', Token::NotEquiv, Token::Not);
	case '&': return AddIfNext('&', Token::And, Token::BitAnd);
	case '|': return AddIfNext('|', Token::Or, Token::BitOr);
	case '<': return AddIfNext('=', Token::LessEquiv, Token::Less);
	case '>': return AddIfNext('=', Token::GreaterEquiv, Token::Greater);
	case '"': return LexString();
	case '\'': return LexAlpha();
	case '-':
		if (Peek() == '-')
		{
			Next();
			return Add(Token::Decrement);
		}
		if (Peek() == '=')
		{
			Next();
			return Add(Token::MinusAssign);
		}
		return Add(Token::Minus);

	case '.':
		if (Peek() == '.')
		{
			Next();
			if (Peek() == '.')
			{
				Next();
				return Add(Token::Replace, 3);
			}
			return Fail("Two dots");
		}
		return Add(Token::Dot);

	case '+':
		if (Peek() == '+')
		{
			Next();
			return Add(Token::Increment);
		}
		if (Peek() == '=')
		{
			Next();
			return Add(Token::PlusAssign);
		}
		return Add(Token::Plus);

	case '/':
		if (Peek() == '/')
		{
			Next();
			int start = offset;
			while (Next() != '\n')
				;
			return Add(Token::Comment, offset - start);
		}
		return Add(Token::Divide);
	}

	LexError("Unrecognised %c");

	return false;
}

std::string Lexer::CreateError(Token tok, const char *fmt, ...)
{
	char buff0[2000];
	va_list ap;
	va_start(ap, fmt);
	vsprintf_s(buff0, fmt, ap);

	const char *fmt1 = "%s(%d):[%d]: %s\n";
	char buff[2000];
	sprintf_s(buff, fmt1, "", tok.lineNumber, tok.slice.Start, buff0);
	int beforeContext = 1;
	int afterContext = 0;

	const Lexer &lex = *tok.lexer;
	int start = std::max(0, tok.lineNumber - beforeContext);
	int end = std::min((int)lex.lines.size() - 1, tok.lineNumber + afterContext);

	strstream err;
	err << buff << endl;
	for (int n = start; n <= end; ++n)
	{
		for (auto ch : lex.lines[n])
		{
			if (ch == '\t')
				err << "    ";
			else
				err << ch;
		}

		if (n == tok.lineNumber)
		{
			for (int ch = 0; ch < (int)lex.lines[n].size(); ++ch)
			{
				if (lex.lines[tok.lineNumber][ch] == '\t')
					err << "    ";
				else if (ch == tok.slice.Start)
				{
					err << '^';
					break;
				}
			}

			err << endl;
		}
	}

	err << ends;

	return err.str();
}

bool Process::Fail(const std::string &err)
{
	Failed = true;
	Error = err;

	return false;
}

bool Process::Fail(const char *fmt, ...)
{
	va_list ap;
	va_start(ap, fmt);
	char buffer[1000];
	vsprintf_s(buffer, fmt, ap);
	return Fail(std::string(buffer));
}

char Lexer::Current() const
{
	if (lineNumber == (int)lines.size())
		return 0;

	return Line()[offset];
}

const std::string &Lexer::Line() const
{
	return lines[lineNumber];
}

char Lexer::Next()
{
	if (EndOfLine())
	{
		offset = 0;
		++lineNumber;
	}
	else
		++offset;

	if (lineNumber == (int)lines.size())
		return 0;

	return Line()[offset];
}

char Lexer::Peek() const
{
	if (EndOfLine())
		return 0;

	return Line()[offset + 1];
}

void Lexer::CreateLines()
{
	// ensure we end with a newline.
	input.push_back('\n');

	size_t lineStart = 0;
	for (size_t n = 0; n < input.size(); ++n)
	{
		if (input[n] == '\n')
		{
			lines.push_back(input.substr(lineStart, n - lineStart + 1));
			lineStart = n + 1;
		}
	}
}

bool Lexer::EndOfLine() const
{
	return offset == (int)Line().size() - 1;
}

bool Lexer::AddIfNext(char ch, Token::Type thenType, Token::Type elseType)
{
	if (Peek() == ch)
	{
		Next();
		return Add(thenType, 2);
	}

	return Add(elseType, 1);
}

bool Lexer::AddTwoCharOp(Token::Type ty)
{
	Add(ty, 2);
	Next();

	return true;
}

bool Lexer::LexString()
{
	int start = offset;
	Next();
	while (!Failed && Current() != '"')
	{
		if (Current() == '\\')
		{
			switch (Next())
			{
			case '"':
			case 'n':
			case 't':
				break;

			default:
				LexError("Bad escape sequence %c");
				return false;
			}
		}

		if (Peek() == 0)
		{
			Fail("Bad string literal");
			return false;
		}

		Next();
	}

	Next();

	// the +1 and -1 to remove the start and end double quote characters
	tokens.push_back(Token(Token::String, *this, lineNumber, Slice(start + 1, offset - 1)));
	return true;
}

void Lexer::LexError(const char *text)
{
	Fail(CreateError(Token(Token::None, *this, lineNumber, Slice(offset, offset)), text, Current()));
}

KAI_END

<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    TestAnimationScene.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/

// Animate a sphere source.
// Original code from
// http://www.vtk.org/pipermail/vtkusers/2005-April/079316.html

#include "vtkTestUtilities.h"
#include "vtkRegressionTestImage.h"

#include "vtkAnimationCue.h"
#include "vtkRenderer.h"
#include "vtkSphereSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkCommand.h"
#include "vtkAnimationScene.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"

class CueAnimator
{
public:
  CueAnimator()
    {
      this->SphereSource=0;
      this->Mapper=0;
      this->Actor=0;
    }

  ~CueAnimator()
    {
      this->Cleanup();
    }

  void StartCue(vtkAnimationCue::AnimationCueInfo *info,
                vtkRenderer *ren)
    {
      cout << "*** IN StartCue " << endl;
      this->SphereSource=vtkSphereSource::New();
      this->SphereSource->SetRadius(0.5);

      this->Mapper=vtkPolyDataMapper::New();
      this->Mapper->SetInputConnection(this->SphereSource->GetOutputPort());

      this->Actor=vtkActor::New();
      this->Actor->SetMapper(this->Mapper);

      ren->AddActor(this->Actor);
      ren->ResetCamera();
      ren->Render();
    }

  void Tick(vtkAnimationCue::AnimationCueInfo *info,
            vtkRenderer *ren)
    {
      double newradius=0.1 +
        (static_cast<double>(info->AnimationTime -
                             info->StartTime)/
         static_cast<double>(info->EndTime-info->StartTime)) * 1;
      this->SphereSource->SetRadius(newradius);
      this->SphereSource->Update();
      ren->Render();
    }

  void EndCue(vtkAnimationCue::AnimationCueInfo *info,
              vtkRenderer* ren)
    {
      // don't remove the actor for the regression image.
//      ren->RemoveActor(this->Actor);
      this->Cleanup();
    }

protected:
  vtkSphereSource *SphereSource;
  vtkPolyDataMapper *Mapper;
  vtkActor *Actor;

  void Cleanup()
    {
      if(this->SphereSource!=0)
        {
        this->SphereSource->Delete();
        this->SphereSource=0;
        }

      if(this->Mapper!=0)
        {
        this->Mapper->Delete();
        this->Mapper=0;
        }
      if(this->Actor!=0)
        {
        this->Actor->Delete();
        this->Actor=0;
        }
    }
};

class vtkAnimationCueObserver : public vtkCommand
{
public:
  static vtkAnimationCueObserver *New()
    {
      return new vtkAnimationCueObserver;
    }

  virtual void Execute(vtkObject *caller,
                       unsigned long event,
                       void *calldata)
    {
      if(this->Animator!=0 && this->Renderer!=0)
        {
        vtkAnimationCue::AnimationCueInfo *info=
          static_cast<vtkAnimationCue::AnimationCueInfo *>(calldata);
        switch(event)
          {
          case vtkCommand::StartAnimationCueEvent:
            this->Animator->StartCue(info,this->Renderer);
            break;
          case vtkCommand::EndAnimationCueEvent:
            this->Animator->EndCue(info,this->Renderer);
            break;
          case vtkCommand::AnimationCueTickEvent:
            this->Animator->Tick(info,this->Renderer);
            break;
          }
        }
      if(this->RenWin!=0)
        {
        this->RenWin->Render();
        }
    }

  vtkRenderer *Renderer;
  vtkRenderWindow *RenWin;
  CueAnimator *Animator;
protected:
  vtkAnimationCueObserver()
    {
      this->Renderer=0;
      this->Animator=0;
      this->RenWin=0;
    }
};

int TestAnimationScene(int argc, char *argv[])
{
  // Create the graphics structure. The renderer renders into the
  // render window.
  vtkRenderWindowInteractor *iren=vtkRenderWindowInteractor::New();
  vtkRenderer *ren1=vtkRenderer::New();
  vtkRenderWindow *renWin=vtkRenderWindow::New();
  renWin->SetMultiSamples(0);
  iren->SetRenderWindow(renWin);
  renWin->AddRenderer(ren1);
  renWin->Render();

  // Create an Animation Scene
  vtkAnimationScene *scene=vtkAnimationScene::New();
  if(argc>=2 && strcmp(argv[1],"-real")==0)
    {
    cout << "real-time mode" << endl;
    scene->SetModeToRealTime();
    }
  else
    {
    cout << "sequence mode" << endl;
    scene->SetModeToSequence();
    }
  scene->SetLoop(0);
  scene->SetFrameRate(5);
  scene->SetStartTime(3);
  scene->SetEndTime(20);

  // Create an Animation Cue.
  vtkAnimationCue *cue1=vtkAnimationCue::New();
  cue1->SetStartTime(5);
  cue1->SetEndTime(23);
  scene->AddCue(cue1);

  // Create cue animator;
  CueAnimator animator;

  // Create Cue observer.
  vtkAnimationCueObserver *observer=vtkAnimationCueObserver::New();
  observer->Renderer=ren1;
  observer->Animator=&animator;
  observer->RenWin=renWin;
  cue1->AddObserver(vtkCommand::StartAnimationCueEvent,observer);
  cue1->AddObserver(vtkCommand::EndAnimationCueEvent,observer);
  cue1->AddObserver(vtkCommand::AnimationCueTickEvent,observer);

  scene->Play();
  scene->Stop();

  int retVal=vtkRegressionTestImage(renWin);
  if(retVal==vtkRegressionTester::DO_INTERACTOR)
    {
    iren->Start();
    }
  iren->Delete();

  ren1->Delete();
  renWin->Delete();
  scene->Delete();
  cue1->Delete();
  observer->Delete();
  return !retVal;
}
<commit_msg>COMP:Fixed warnings.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestAnimationScene.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/

// Animate a sphere source.
// Original code from
// http://www.vtk.org/pipermail/vtkusers/2005-April/079316.html

#include "vtkTestUtilities.h"
#include "vtkRegressionTestImage.h"

#include "vtkAnimationCue.h"
#include "vtkRenderer.h"
#include "vtkSphereSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkCommand.h"
#include "vtkAnimationScene.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"

class CueAnimator
{
public:
  CueAnimator()
    {
      this->SphereSource=0;
      this->Mapper=0;
      this->Actor=0;
    }

  ~CueAnimator()
    {
      this->Cleanup();
    }

  void StartCue(vtkAnimationCue::AnimationCueInfo *vtkNotUsed(info),
                vtkRenderer *ren)
    {
      cout << "*** IN StartCue " << endl;
      this->SphereSource=vtkSphereSource::New();
      this->SphereSource->SetRadius(0.5);

      this->Mapper=vtkPolyDataMapper::New();
      this->Mapper->SetInputConnection(this->SphereSource->GetOutputPort());

      this->Actor=vtkActor::New();
      this->Actor->SetMapper(this->Mapper);

      ren->AddActor(this->Actor);
      ren->ResetCamera();
      ren->Render();
    }

  void Tick(vtkAnimationCue::AnimationCueInfo *info,
            vtkRenderer *ren)
    {
      double newradius=0.1 +
        (static_cast<double>(info->AnimationTime -
                             info->StartTime)/
         static_cast<double>(info->EndTime-info->StartTime)) * 1;
      this->SphereSource->SetRadius(newradius);
      this->SphereSource->Update();
      ren->Render();
    }

  void EndCue(vtkAnimationCue::AnimationCueInfo *vtkNotUsed(info),
              vtkRenderer *ren)
    {
      (void)ren;
      // don't remove the actor for the regression image.
//      ren->RemoveActor(this->Actor);
      this->Cleanup();
    }

protected:
  vtkSphereSource *SphereSource;
  vtkPolyDataMapper *Mapper;
  vtkActor *Actor;

  void Cleanup()
    {
      if(this->SphereSource!=0)
        {
        this->SphereSource->Delete();
        this->SphereSource=0;
        }

      if(this->Mapper!=0)
        {
        this->Mapper->Delete();
        this->Mapper=0;
        }
      if(this->Actor!=0)
        {
        this->Actor->Delete();
        this->Actor=0;
        }
    }
};

class vtkAnimationCueObserver : public vtkCommand
{
public:
  static vtkAnimationCueObserver *New()
    {
      return new vtkAnimationCueObserver;
    }

  virtual void Execute(vtkObject *vtkNotUsed(caller),
                       unsigned long event,
                       void *calldata)
    {
      if(this->Animator!=0 && this->Renderer!=0)
        {
        vtkAnimationCue::AnimationCueInfo *info=
          static_cast<vtkAnimationCue::AnimationCueInfo *>(calldata);
        switch(event)
          {
          case vtkCommand::StartAnimationCueEvent:
            this->Animator->StartCue(info,this->Renderer);
            break;
          case vtkCommand::EndAnimationCueEvent:
            this->Animator->EndCue(info,this->Renderer);
            break;
          case vtkCommand::AnimationCueTickEvent:
            this->Animator->Tick(info,this->Renderer);
            break;
          }
        }
      if(this->RenWin!=0)
        {
        this->RenWin->Render();
        }
    }

  vtkRenderer *Renderer;
  vtkRenderWindow *RenWin;
  CueAnimator *Animator;
protected:
  vtkAnimationCueObserver()
    {
      this->Renderer=0;
      this->Animator=0;
      this->RenWin=0;
    }
};

int TestAnimationScene(int argc, char *argv[])
{
  // Create the graphics structure. The renderer renders into the
  // render window.
  vtkRenderWindowInteractor *iren=vtkRenderWindowInteractor::New();
  vtkRenderer *ren1=vtkRenderer::New();
  vtkRenderWindow *renWin=vtkRenderWindow::New();
  renWin->SetMultiSamples(0);
  iren->SetRenderWindow(renWin);
  renWin->AddRenderer(ren1);
  renWin->Render();

  // Create an Animation Scene
  vtkAnimationScene *scene=vtkAnimationScene::New();
  if(argc>=2 && strcmp(argv[1],"-real")==0)
    {
    cout << "real-time mode" << endl;
    scene->SetModeToRealTime();
    }
  else
    {
    cout << "sequence mode" << endl;
    scene->SetModeToSequence();
    }
  scene->SetLoop(0);
  scene->SetFrameRate(5);
  scene->SetStartTime(3);
  scene->SetEndTime(20);

  // Create an Animation Cue.
  vtkAnimationCue *cue1=vtkAnimationCue::New();
  cue1->SetStartTime(5);
  cue1->SetEndTime(23);
  scene->AddCue(cue1);

  // Create cue animator;
  CueAnimator animator;

  // Create Cue observer.
  vtkAnimationCueObserver *observer=vtkAnimationCueObserver::New();
  observer->Renderer=ren1;
  observer->Animator=&animator;
  observer->RenWin=renWin;
  cue1->AddObserver(vtkCommand::StartAnimationCueEvent,observer);
  cue1->AddObserver(vtkCommand::EndAnimationCueEvent,observer);
  cue1->AddObserver(vtkCommand::AnimationCueTickEvent,observer);

  scene->Play();
  scene->Stop();

  int retVal=vtkRegressionTestImage(renWin);
  if(retVal==vtkRegressionTester::DO_INTERACTOR)
    {
    iren->Start();
    }
  iren->Delete();

  ren1->Delete();
  renWin->Delete();
  scene->Delete();
  cue1->Delete();
  observer->Delete();
  return !retVal;
}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    TestAreaSelections.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
// This tests vtkHardwareSelector, vtkExtractSelectedFrustum,
// vtkRenderedAreaPicker, and vtkInteractorStyleRubberBandPick.
//
// The command line arguments are:
// -I        => run in interactive mode; unless this is used, the program will
//              not allow interaction and exit

#include "vtkTestUtilities.h"
#include "vtkRegressionTestImage.h"

#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSphereSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkInteractorStyleRubberBandPick.h"
#include "vtkCallbackCommand.h"
#include "vtkHardwareSelector.h"
#include "vtkSelection.h"
#include "vtkExtractSelectedPolyDataIds.h"
#include "vtkIdTypeArray.h"
#include "vtkRenderedAreaPicker.h"
#include "vtkCamera.h"
#include "vtkImageMandelbrotSource.h"
#include "vtkImageActor.h"
#include "vtkExtractSelectedFrustum.h"
#include "vtkDataSetMapper.h"

#include "vtkDataSetReader.h"

vtkRenderer *renderer = NULL;
vtkSphereSource* SS1 = NULL;
vtkDataSetMapper* sMap = NULL;
vtkPolyData* emptyPD = NULL;

static void EndPick(vtkObject *vtkNotUsed( caller ),
                    unsigned long vtkNotUsed(eventId),
                    void *, void *)
{
  vtkHardwareSelector *sel = vtkHardwareSelector::New();
  sel->SetRenderer(renderer);

  double x0 = renderer->GetPickX1();
  double y0 = renderer->GetPickY1();
  double x1 = renderer->GetPickX2();
  double y1 = renderer->GetPickY2();

  sel->SetArea(static_cast<int>(x0),static_cast<int>(y0),static_cast<int>(x1),
               static_cast<int>(y1));
  vtkSelection* res = sel->Select();

  /*
  cerr << "x0 " << x0 << " y0 " << y0 << "\t";
  cerr << "x1 " << x1 << " y1 " << y1 << endl;
  vtkIdTypeArray *a = vtkIdTypeArray::New();
  sel->GetSelectedIds(a);
  cerr << "numhits = " << a->GetNumberOfTuples() << endl;
  sel->PrintSelectedIds(a);
  a->Delete();
  */

  vtkSelection *cellids = res->GetChild(0);
  vtkExtractSelectedPolyDataIds *extr = vtkExtractSelectedPolyDataIds::New();
  if (cellids)
    {
    extr->SetInput(0, SS1->GetOutput());
    extr->SetInput(1, cellids);
    extr->Update();
    sMap->SetInput(extr->GetOutput());
    }
  else
    {
    cerr << "Empty color buffer selection -" << endl;
    cerr << "Check display color depth. Must be at least 24 bit." << endl;
    sMap->SetInput(emptyPD);
    }

  sel->Delete();
  res->Delete();
  extr->Delete();
}

int TestAreaSelections(int argc, char* argv[])
{
  // Standard rendering classes
  renderer = vtkRenderer::New();
  vtkRenderWindow *renWin = vtkRenderWindow::New();
  renWin->AddRenderer(renderer);
  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
  iren->SetRenderWindow(renWin);

  //set up the view
  renderer->GetActiveCamera()->SetPosition(  1.5, -0.75, 7);
  renderer->GetActiveCamera()->SetFocalPoint(1.5, -0.75, 0);
  renderer->GetActiveCamera()->SetViewUp(     0,   1,   0);
  renderer->SetBackground(0.0,0.0,0.0);
  renWin->SetSize(300,300);

  //use the rubber band pick interactor style
  vtkRenderWindowInteractor* rwi = renWin->GetInteractor();
  vtkInteractorStyleRubberBandPick *rbp =
    vtkInteractorStyleRubberBandPick::New();
  rwi->SetInteractorStyle(rbp);

  vtkRenderedAreaPicker *areaPicker = vtkRenderedAreaPicker::New();
  rwi->SetPicker(areaPicker);

  ////////////////////////////////////////////////////////////
  //Create a unstructured grid data source to test FrustumExtractor with.
  vtkDataSetReader *reader = vtkDataSetReader::New();
  char *cfname=vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/SampleStructGrid.vtk");
  reader->SetFileName(cfname);

  vtkDataSetMapper *map1 = vtkDataSetMapper::New();
  map1->SetInput(reader->GetOutput());

  vtkActor *act1 = vtkActor::New();
  act1->SetMapper(map1);
  act1->PickableOff(); //prevents the visible cell selector from trying
  renderer->AddActor(act1);

  //frustum extractor works on geometry and doesn't care about pickability
  vtkExtractSelectedFrustum *extractor = vtkExtractSelectedFrustum::New();
  extractor->SetInputConnection(reader->GetOutputPort());
  extractor->PreserveTopologyOff();
  extractor->SetFrustum(areaPicker->GetFrustum());

  vtkDataSetMapper *eMap = vtkDataSetMapper::New();
  eMap->SetInput(vtkDataSet::SafeDownCast(extractor->GetOutput()));

  vtkActor *eAct = vtkActor::New();
  eAct->SetPosition(2,0,0);
  eAct->SetMapper(eMap);
  eAct->PickableOff();
  renderer->AddActor(eAct);

  ////////////////////////////////////////////////////////////
  emptyPD = vtkPolyData::New();

  int res = 20;
  SS1 = vtkSphereSource::New();
  SS1->SetThetaResolution(res);
  SS1->SetPhiResolution(res);
  SS1->SetRadius(0.5);
  SS1->SetCenter(0.5,-1.5,0);
  vtkPolyDataMapper *map2 = vtkPolyDataMapper::New();
  map2->SetInput(SS1->GetOutput());

  vtkActor* act2 = vtkActor::New();
  act2->SetMapper(map2);
  act2->PickableOn(); //lets the HardwareSelector select in it
  renderer->AddActor(act2);

  sMap = vtkDataSetMapper::New();
  sMap->SetInput(SS1->GetOutput());

  vtkActor *sAct = vtkActor::New();
  sAct->SetMapper(sMap);
  sAct->SetPosition(2,0,0);
  sAct->PickableOff();
  renderer->AddActor(sAct);

  //pass pick events to the HardwareSelector
  vtkCallbackCommand *cbc = vtkCallbackCommand::New();
  cbc->SetCallback(EndPick);
  cbc->SetClientData(renderer);
  rwi->AddObserver(vtkCommand::EndPickEvent,cbc);
  cbc->Delete();

  ////////////////////////////////////////////////////////////

  //run the test

  renWin->Render();
  areaPicker->AreaPick(51,78,82,273,renderer);
  EndPick(NULL, 0, NULL, NULL);
  renWin->Render();

  int retVal = vtkRegressionTestImage( renWin );
  if ( retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    iren->Start();
    }

  // Cleanup
  renderer->Delete();
  renWin->Delete();
  iren->Delete();
  rbp->Delete();
  areaPicker->Delete();
  reader->Delete();
  map1->Delete();
  act1->Delete();
  extractor->Delete();
  eMap->Delete();
  eAct->Delete();
  emptyPD->Delete();
  SS1->Delete();
  map2->Delete();
  act2->Delete();
  sMap->Delete();
  sAct->Delete();
  delete [] cfname;
  return !retVal;
}
<commit_msg>BUG: fixed leaks<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestAreaSelections.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
// This tests vtkHardwareSelector, vtkExtractSelectedFrustum,
// vtkRenderedAreaPicker, and vtkInteractorStyleRubberBandPick.
//
// The command line arguments are:
// -I        => run in interactive mode; unless this is used, the program will
//              not allow interaction and exit

#include "vtkTestUtilities.h"
#include "vtkRegressionTestImage.h"

#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSphereSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkInteractorStyleRubberBandPick.h"
#include "vtkCallbackCommand.h"
#include "vtkHardwareSelector.h"
#include "vtkSelection.h"
#include "vtkExtractSelectedPolyDataIds.h"
#include "vtkIdTypeArray.h"
#include "vtkRenderedAreaPicker.h"
#include "vtkCamera.h"
#include "vtkImageMandelbrotSource.h"
#include "vtkImageActor.h"
#include "vtkExtractSelectedFrustum.h"
#include "vtkDataSetMapper.h"
#include "vtkSmartPointer.h"

#include "vtkDataSetReader.h"

vtkSmartPointer<vtkRenderer> renderer;
vtkSmartPointer<vtkSphereSource> SS1;
vtkSmartPointer<vtkDataSetMapper> sMap;
vtkSmartPointer<vtkPolyData> emptyPD;

#define MY_CREATE_NEW(class, variable)\
  vtkSmartPointer<class> variable = vtkSmartPointer<class>::New();

static void EndPick(vtkObject *vtkNotUsed( caller ),
                    unsigned long vtkNotUsed(eventId),
                    void *, void *)
{
  MY_CREATE_NEW(vtkHardwareSelector, sel);
  sel->SetRenderer(renderer);

  double x0 = renderer->GetPickX1();
  double y0 = renderer->GetPickY1();
  double x1 = renderer->GetPickX2();
  double y1 = renderer->GetPickY2();

  sel->SetArea(static_cast<int>(x0),static_cast<int>(y0),static_cast<int>(x1),
               static_cast<int>(y1));
  vtkSmartPointer<vtkSelection> res;
  res.TakeReference(sel->Select());

  /*
  cerr << "x0 " << x0 << " y0 " << y0 << "\t";
  cerr << "x1 " << x1 << " y1 " << y1 << endl;
  vtkIdTypeArray *a = vtkIdTypeArray::New();
  sel->GetSelectedIds(a);
  cerr << "numhits = " << a->GetNumberOfTuples() << endl;
  sel->PrintSelectedIds(a);
  a->Delete();
  */

  vtkSelection *cellids = res->GetChild(0);
  MY_CREATE_NEW(vtkExtractSelectedPolyDataIds, extr);
  if (cellids)
    {
    extr->SetInput(0, SS1->GetOutput());
    extr->SetInput(1, cellids);
    extr->Update();
    sMap->SetInput(extr->GetOutput());
    }
  else
    {
    cerr << "Empty color buffer selection -" << endl;
    cerr << "Check display color depth. Must be at least 24 bit." << endl;
    sMap->SetInput(emptyPD);
    }
}

int TestAreaSelections(int argc, char* argv[])
{
  // Standard rendering classes
  renderer = vtkSmartPointer<vtkRenderer>::New();
  MY_CREATE_NEW(vtkRenderWindow, renWin);
  renWin->AddRenderer(renderer);
  MY_CREATE_NEW(vtkRenderWindowInteractor, iren);
  iren->SetRenderWindow(renWin);

  //set up the view
  renderer->GetActiveCamera()->SetPosition(  1.5, -0.75, 7);
  renderer->GetActiveCamera()->SetFocalPoint(1.5, -0.75, 0);
  renderer->GetActiveCamera()->SetViewUp(     0,   1,   0);
  renderer->SetBackground(0.0,0.0,0.0);
  renWin->SetSize(300,300);

  //use the rubber band pick interactor style
  vtkRenderWindowInteractor* rwi = renWin->GetInteractor();
  MY_CREATE_NEW(vtkInteractorStyleRubberBandPick, rbp);
  rwi->SetInteractorStyle(rbp);

  MY_CREATE_NEW(vtkRenderedAreaPicker, areaPicker);
  rwi->SetPicker(areaPicker);

  ////////////////////////////////////////////////////////////
  //Create a unstructured grid data source to test FrustumExtractor with.
  MY_CREATE_NEW(vtkDataSetReader, reader);
  char *cfname=vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/SampleStructGrid.vtk");
  reader->SetFileName(cfname);

  MY_CREATE_NEW(vtkDataSetMapper, map1);
  map1->SetInput(reader->GetOutput());

  MY_CREATE_NEW(vtkActor, act1);
  act1->SetMapper(map1);
  act1->PickableOff(); //prevents the visible cell selector from trying
  renderer->AddActor(act1);

  //frustum extractor works on geometry and doesn't care about pickability
  MY_CREATE_NEW(vtkExtractSelectedFrustum, extractor);
  extractor->SetInputConnection(reader->GetOutputPort());
  extractor->PreserveTopologyOff();
  extractor->SetFrustum(areaPicker->GetFrustum());

  MY_CREATE_NEW(vtkDataSetMapper, eMap);
  eMap->SetInput(vtkDataSet::SafeDownCast(extractor->GetOutput()));

  MY_CREATE_NEW(vtkActor, eAct);
  eAct->SetPosition(2,0,0);
  eAct->SetMapper(eMap);
  eAct->PickableOff();
  renderer->AddActor(eAct);

  ////////////////////////////////////////////////////////////
  emptyPD = vtkSmartPointer<vtkPolyData>::New();

  int res = 20;
  SS1 = vtkSmartPointer<vtkSphereSource>::New();
  SS1->SetThetaResolution(res);
  SS1->SetPhiResolution(res);
  SS1->SetRadius(0.5);
  SS1->SetCenter(0.5,-1.5,0);
  MY_CREATE_NEW(vtkPolyDataMapper, map2);
  map2->SetInput(SS1->GetOutput());

  MY_CREATE_NEW(vtkActor, act2);
  act2->SetMapper(map2);
  act2->PickableOn(); //lets the HardwareSelector select in it
  renderer->AddActor(act2);

  sMap = vtkSmartPointer<vtkDataSetMapper>::New();
  sMap->SetInput(SS1->GetOutput());

  MY_CREATE_NEW(vtkActor, sAct);
  sAct->SetMapper(sMap);
  sAct->SetPosition(2,0,0);
  sAct->PickableOff();
  renderer->AddActor(sAct);

  //pass pick events to the HardwareSelector
  MY_CREATE_NEW(vtkCallbackCommand, cbc);
  cbc->SetCallback(EndPick);
  cbc->SetClientData(renderer);
  rwi->AddObserver(vtkCommand::EndPickEvent,cbc);

  ////////////////////////////////////////////////////////////

  //run the test

  renWin->Render();
  areaPicker->AreaPick(51,78,82,273,renderer);
  EndPick(NULL, 0, NULL, NULL);
  renWin->Render();

  int retVal = vtkRegressionTestImage( renWin );
  if ( retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    iren->Start();
    }

  // Cleanup
  delete [] cfname;
  return !retVal;
}
<|endoftext|>