Mouse-arrastrar objeto en OpenGL / GLUT

He estado buscando todo el día un tutorial o un código de ejemplo para un progtwig simple: haga clic en el objeto (como un rectángulo 2d, por ejemplo) luego, mientras mantiene presionado el mouse, el objeto sigue al mouse, luego, al soltar el mouse, el objeto permanece en nueva ubicacion. En otras palabras, quiero entender cómo arrastrar y soltar un objeto con los eventos del mouse.

¿Podría alguien ayudarme a indicarme la dirección correcta de cualquier fuente útil de información relacionada con este problema?

Gracias por todas las respuestas hasta ahora.

He resuelto cómo hacerlo, así que seguiré adelante y responderé mi propia pregunta.

Estoy usando GLUT como un controlador de ratón:

  1. Cuando se hace clic y se mueve el mouse (glutMotionFunc), se llama a la función de arrastre.

  2. En la función de arrastre, las coordenadas del mouse (x, y) se convierten en una estructura de puntos mientras se convierten en coordenadas de ventana.

  3. Si el mouse está dentro del cuadrado, arrastre el cuadrado cambiando sus coordenadas y vuelva a mostrarlo.

Todavía soy muy nuevo en OpenGL y C ++, así que me disculpo por la encoding desordenada. Estoy un poco frustrado al hacerlo de esta manera, ya que el cuadrado redondeado hace que parezca que el cursor se ajusta al centro. Acojo con satisfacción las soluciones alternativas a este problema y la crítica de mi código, con fines de aprendizaje.

CÓDIGO (incluido glut y usando namespace std):

// points structure made of two coordinates; x and y struct Points { float x,y; // initializor Points() { x = 0.0; y = 0.0; } // constructor Points(float _x, float _y) : x(_x), y(_y) {} }; // square made of 4 points class Square { public: Points pts[4]; // square structure Square(); // initialize constructor void draw(Square *sqr); // draw square Points mouse(int x, int y); // get mouse coordintaes Square* drag(Square *sqr, Points *mouse); // change points of sqr }; // square constructor Square::Square() { pts[0] = Points(0.2,0.2); pts[1] = Points(0.4,0.2); pts[2] = Points(0.4,0.4); pts[3] = Points(0.2,0.4); }; // draw function void Square::draw(Square *sqr) { // draw square fill int i; glColor3f(0.2, 0.2, 0.2); glBegin(GL_QUADS); for (i = 0; i < 4; ++i) { glVertex2f(sqr->pts[i].x, sqr->pts[i].y); } glEnd(); // draw square points i = 0; glColor3f(1.0, 1.0, 1.0); glBegin(GL_POINTS); for (i = 0; i < 4; ++i) { glVertex2f(sqr->pts[i].x, sqr->pts[i].y); } glEnd(); } // mouse function Points Square::mouse(int x, int y) { int windowWidth = 400, windowHeight = 400; return Points(float(x)/windowWidth, 1.0 - float(y)/windowHeight); } // drag function Square* Square::drag(Square *sqr, Points *mouse) { sqr->pts[0].x = mouse->x - 0.1; sqr->pts[0].y = mouse->y - 0.1; sqr->pts[1].x = mouse->x + 0.1; sqr->pts[1].y = mouse->y - 0.1; sqr->pts[3].x = mouse->x - 0.1; sqr->pts[3].y = mouse->y + 0.1; sqr->pts[2].x = mouse->x + 0.1; sqr->pts[2].y = mouse->y + 0.1; return sqr; } // GLOBAL // create square object Square* sqr = new Square; // display at start void display() { glClear(GL_COLOR_BUFFER_BIT); sqr->draw(sqr); glFlush(); } // drag function void drag (int x, int y) { // int x and y of mouse converts to screen coordinates // returns the point as mousePt Points mousePt = sqr->mouse(x,y); //create pointer to window point coordinates Points* mouse = &mousePt; // if the mouse is within the square if (mouse->x > sqr->pts[0].x && mouse->y > sqr->pts[0].y) { if (mouse->x < sqr->pts[2].x && mouse->y < sqr->pts[2].y) { // then drag by chaning square coordinates relative to mouse sqr->drag(sqr,mouse); glutPostRedisplay(); } } } void Initialize() { glClearColor(0.0, 0.0, 0.0, 0.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); } int main(int iArgc, char** cppArgv) { glutInit(&iArgc, cppArgv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(400, 400); glutInitWindowPosition(200, 200); glutCreateWindow("Move Box"); glutMotionFunc(drag); Initialize(); glutDisplayFunc(display); glutMainLoop(); return 0; } 

A OpenGL solo le preocupa el proceso de dibujo. Todo lo demás (entrada del mouse, selección de objetos, gestión de escenas / alteraciones, etc.) depende completamente de usted para implementar.

Aquí hay un esquema aproximado:

  1. Instale un controlador de eventos con un clic del mouse (el método exacto a usar depende del marco utilizado y / o el sistema operativo)

  2. En el controlador de eventos, haga clic con el mouse y realice una operación de picking. Por lo general, esto implica que no se proyecte la posición de la ventana del mouse en el espacio mundial (vea gluUnproject), lo que resulta en un rayo. Prueba cada objeto en la escena si se cruza con el rayo; tendrás que implementar esto tú mismo, porque OpenGL simplemente dibuja una cosa (no hay tal cosa como una “escena” en OpenGL).

  3. Si un objeto ha sido seleccionado regístrelo para manipularlo en el controlador de arrastre del mouse

  4. Cada vez que se produce un evento de arrastre del mouse, ajuste los datos de posición del objeto y el desencadenante de la pantalla OpenGL (siempre se vuelve a dibujar todo en OpenGL).

  5. Cuando se suelta el mouse, anule el registro del objeto desde el controlador de arrastre.

Como lo mencionaron otros, OpenGL no maneja la entrada del usuario. Quieres usar una biblioteca para eso. Si desea una solución más completa, incluso puede utilizar un render o un motor de física más completo.

Para una entrada de usuario simple, puede usar SDL (por ejemplo, esto es para la entrada del mouse).

Para cosas más completas en 2D, puedes usar Box2D . Aquí hay un montón de tutoriales.

La solución de peso pesado es un motor de render completo, como Ogre3D o CrystalSpace .

Como lo mencionaron otros, debe obtener un controlador de mouse para obtener primero la posición del mouse. Entonces necesitas una forma de escoger un objeto. Tienes algunas opciones para hacer el picking en OpenGL.

  1. Si está utilizando OpenGL clásico, puede usar el búfer de selección. El siguiente enlace es un buen tutorial http://www.lighthouse3d.com/opengl/picking/index.php3?openglway
  2. Si está utilizando el opengl moderno, que está basado en el sombreado, puede usar el picking basado en FBO. http://ogldev.atspace.co.uk/www/tutorial29/tutorial29.html
  3. Siempre puede implementar un seguimiento de rayos seleccionándose usted mismo en ambos casos. El gluUnproject puede ayudar mucho en la implementación. http://schabby.de/picking-opengl-ray-tracing/

Después de eso, solo necesita actualizar la posición del objeto de acuerdo con el movimiento o la aceleración del mouse.