0

I'm trying to make a color picker tool in OpenGL. It works you can use the code below. However there is one glaring issue, if you test the program you will find that if you click the black background, the color selected will become black. So my question is how do I change the code such that it recognizes which polygon I clicked or recognizes that I clicked on something or a polygon.

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <cmath>
#include <iterator>

//static void mouseButtonCallback(GLFWwindow* window, int button, int action, int mod);
static void mouse_cursor_callback(GLFWwindow* window, double xpos, double ypos);
float randfloat(){
  float r = ((float)(rand() % 10))/10;
  return r;
}
class RGB{
  public:
    float r;
    float g;
    float b;
    void setColor(float _r, float _g, float _b){
      r = _r;
      g = _g;
      b = _b;
    }
};
RGB selected_col;
RGB mixColor(RGB color1, RGB color2){
  float r = 0;
  float g = 0;
  float b = 0;
  r = sqrt((pow(color1.r,2)+pow(color2.r,2))/2);
  g = sqrt((pow(color1.g,2)+pow(color2.g,2))/2);
  b = sqrt((pow(color1.b,2)+pow(color2.b,2))/2);
  RGB a;
  a.setColor(r,g,b);
  return a;
}


int main() {
  int side_count;
  std::cout<<"Type the no. of sides: "<<std::endl;
  std::cin>>side_count;
  if(side_count < 3){
    return 1;
  }
  srand((unsigned)time(0));
  float rs[side_count];
  float gs[side_count];
  float bs[side_count];
  RGB colors[side_count];
  for (int i=0;i<side_count;i++)
  {
    rs[i] = randfloat();
    gs[i] = randfloat();
    bs[i] = randfloat();
    colors[i].setColor(rs[i],gs[i],bs[i]);
  }

  GLFWwindow* window;
  if (!glfwInit())
    return 1;
  window = glfwCreateWindow(400, 400, "Window", NULL, NULL);

  //glfwSetMouseButtonCallback(window, mouseButtonCallback);
  glfwSetCursorPosCallback(window, mouse_cursor_callback);

  if (!window) {
    glfwTerminate();
    return 1;
  }
  glfwMakeContextCurrent(window);
  if(glewInit()!=GLEW_OK)
    std::cout<<"Error"<<std::endl;
  RGB mcol = colors[1];
  for(int i=0;i<side_count-1;i++)
  {
    mcol = mixColor(mcol, colors[i+1]);
  }
  while(!glfwWindowShouldClose(window)) {
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_POLYGON);
      glColor3f(mcol.r,mcol.g,mcol.b);glVertex2f(0,0);
      //glColor3f(1.0f,0.0f,0.0f);glVertex3f(-0.5f,0.0f,0.0f);
      for(int i=0; i<=side_count;i++)
      {
        float r = rs[i%side_count];
        float g = gs[i%side_count];
        float b = bs[i%side_count];
        float x = 0.5f * sin(2.0*M_PI*i/side_count);
        float y = 0.5f * cos(2.0*M_PI*i/side_count);
        glColor3f(r,g,b);glVertex2f(x,y);
      }
    glEnd();
    glBegin(GL_QUADS);
    glColor3f(selected_col.r, selected_col.g, selected_col.b);glVertex2f(-1.0f,0.5f);
    glColor3f(selected_col.r, selected_col.g, selected_col.b);glVertex2f(-.5f,0.5f);
    glColor3f(selected_col.r, selected_col.g, selected_col.b);glVertex2f(-.5f,1.5f);
    glColor3f(selected_col.r, selected_col.g, selected_col.b);glVertex2f(-1.0f,1.5f);
    glEnd();
    glfwSwapBuffers(window);
    glfwPollEvents();
  }
  glfwTerminate();
  return 0;
}

/*static void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods){
  if(button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS){
    double xPos, yPos;
    glfwGetCursorPos(window, &xPos, &yPos);
    //std::cout<<"X: "<<xPos<<" Y: "<<yPos<<std::endl;
    double x=xPos;
    int height,width;
    glfwGetWindowSize(window, &width, &height);
    double y = height - yPos;
    unsigned char pixel[4];
    glReadPixels(x, y, 1, 1, GL_RGB,GL_UNSIGNED_BYTE, &pixel);
    selected_col.setColor((float)pixel[0]/255,(float)pixel[1]/255,(float)pixel[2]/255);
    //std::cout<<"R: "<<selected_col.r<<" G: "<<selected_col.g<<" B: "<<selected_col.b<<std::endl;
  }
}*/
void mouse_cursor_callback( GLFWwindow * window, double xpos, double ypos)  
{

  if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_RELEASE) 
  {
     return;
  }

  double xPos, yPos;
  glfwGetCursorPos(window, &xPos, &yPos);
  //std::cout<<"X: "<<xPos<<" Y: "<<yPos<<std::endl;
  double x=xPos;
  int height,width;
  glfwGetWindowSize(window, &width, &height);
  double y = height - yPos;
  unsigned char pixel[4];
  glReadPixels(x, y, 1, 1, GL_RGB,GL_UNSIGNED_BYTE, &pixel);
  selected_col.setColor((float)pixel[0]/255,(float)pixel[1]/255,(float)pixel[2]/255);
  //std::cout<<"R: "<<selected_col.r<<" G: "<<selected_col.g<<" B: "<<selected_col.b<<std::endl;
}
genpfault
  • 51,148
  • 11
  • 85
  • 139
  • 2
    The easiest way would be to add a depth or stencil buffer and check these at the clicked position. – Nico Schertler May 11 '19 at 18:01
  • Thanks for the feedback, but is there any resource you know that could help me in implementing this? – Chris Mathew May 11 '19 at 18:17
  • 1
    If you are on windows, simply change your clear command to `glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)`. On click, read the depth: `float depth; glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);`. And finally check if it is `1` (then it is the background). – Nico Schertler May 11 '19 at 19:33
  • @NicoSchertler Thanks for the reply and sorry for the late response. I tried this however the main triangle has a depth of 1 as well as the background. Is there anything i can do to change the depth of the triangle? – Chris Mathew May 12 '19 at 10:33
  • Oh, you probably also need `glEnable(GL_DEPTH_TEST)`. – Nico Schertler May 12 '19 at 16:25

0 Answers0