Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Solved Undefined symbols for architecture x86_64

    Installation and Deployment
    3
    6
    2753
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • ZakkWylde
      ZakkWylde last edited by

      Hi, I'm a newbie of QT and OpenGL, so please bare with me. I'm having an hard time with an example my professor gave in today's lecture.
      I'm using QT Creator 5.5.1 (Clang 6.1) on a OS X, Intel Iris Graphics 6100 1536 MB

      This is the .pro file:

      QT += core gui opengl

      greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

      TARGET = hello_world3D_interaction_todo
      TEMPLATE = app

      SOURCES += main.cpp
      glwidget.cpp
      glew.c
      ppm.cpp

      HEADERS +=
      glwidget.h
      cvec.h
      matrix4.h
      shader.h
      ppm.h

      FORMS += mainwindow.ui

      DISTFILES +=
      shaders/diffuse.fsh
      shaders/solid.fsh
      shaders/basic.vsh

      unix:
      INCLUDEPATH += /usr/local/include
      DEPENDPATH += /usr/local/include

      this is the main.cpp:

      #ifndef GLEW_STATIC
      #define GLEW_STATIC
      #include <GL/glew.h> // the library to load the appropriate OpenGL function
      #endif

      #include <iostream> // C++ I/O library

      #include <QApplication>
      #include <QtOpenGL/QGLFormat>
      #include "glwidget.h"

      int main(int argc, char *argv[])
      {
      // manages the Qt GUI application's control flow and main settings
      QApplication a(argc, argo);

      // specifies the display format of an OpenGL rendering context
      // it will be used to set the widget (window) appropriately
      
      
      QSurfaceFormat glFormat;
      glFormat.setVersion(3, 3);
      glFormat.setProfile(QSurfaceFormat::CoreProfile);
      QSurfaceFormat::setDefaultFormat(glFormat);
      glFormat.setSamples(4);
      // print the OpenGL version and subversion used
      std::cerr << "GL version: " << glFormat.majorVersion() << "." << glFormat.minorVersion() << " ";
      
      // create a GLWidget requesting our format
      // (inherits from QOpenGLWidget, a widget for rendering OpenGL graphics)
      GLWidget widget;
      widget.setFormat(glFormat);
      // show the widget - inside it calls initializeGL, then resizeGL and paintGL
      widget.show();
      
      // enters the main event loop
      return a.exec();
      

      }

      this is the glwidget.cpp

      #ifndef GLEW_STATIC
      #define GLEW_STATIC
      #include <GL/glew.h>
      #endif
      #ifndef SHADER_H
      #include <shader.h>
      #endif

      #include "glwidget.h"
      #include <QCoreApplication>
      #include <QkeyEvent>
      #include <QtGlobal> // if we want to use qwarning

      #include <iostream>
      #include <vector>
      #include <string>
      #include <stdexcept>

      #include "cvec.h"
      #include "matrix4.h"
      #include "ppm.h"

      // for string, vector, iostream, and other standard C++ stuff
      using namespace std;

      // G L O B A L S ///////////////////////////////////////////////////
      static const float g_frustMinFov = 60.0; // A minimal of 60 degree field of view
      static float g_frustFovY = g_frustMinFov; // FOV in y direction (updated by updateFrustFovY)
      static const float g_frustNear = -0.1; // near plane
      static const float g_frustFar = -50.0; // far plane

      //static int g_windowWidth = 512;
      //static int g_windowHeight = 512;
      static int g_windowWidth = 640;
      static int g_windowHeight = 480;

      // --------- Scene
      // define two lights positions in world space
      static const Cvec3 g_light1(2.0, 3.0, 14.0), g_light2(-2, -3.0, -5.0);
      static Matrix4 skyRbt = Matrix4::makeTranslation(Cvec3(0.0, 0.5, 5.0));
      static Matrix4 objRbt[2] = {Matrix4::makeTranslation(Cvec3(-1,0,0)), Matrix4::makeTranslation(Cvec3(1,0,0))};
      static Matrix4 eyeRbt;

      // update g_frustFovY from g_frustMinFov, g_windowWidth, and g_windowHeight
      static void updateFrustFovY() {
      if (g_windowWidth >= g_windowHeight)
      g_frustFovY = g_frustMinFov;
      else {
      const double RAD_PER_DEG = 0.5 * CS175_PI/180;
      g_frustFovY = atan2(sin(g_frustMinFov * RAD_PER_DEG) * g_windowHeight / g_windowWidth, cos(g_frustMinFov * RAD_PER_DEG)) / RAD_PER_DEG;
      }
      }

      // creates the projection matrix of the camera
      static Matrix4 makeProjectionMatrix() {
      return Matrix4::makeProjection(
      g_frustFovY, g_windowWidth / static_cast <double> (g_windowHeight),
      g_frustNear, g_frustFar);
      }

      ///////////////////////////////////////////////////////////////
      // GLWidget constructor
      GLWidget::GLWidget( QWidget* parent ) : QOpenGLWidget( parent )
      {
      // set the window title
      this->setWindowTitle("Hello world 3D (with interaction)");

      // the default polygon visualization is FILL
      polyMode = GL_FILL;
      
      // the default shader is solid
      activeShader = 0;
      
      // the default view is sky camera
      viewMode = 0;
      
      // the default object is sky camera
      objMode = 0;
      
      // the default mode for the auxiliary frame when the sky
      // camera is selected is the sky-sky frame
      mMode = 0;
      
      //qWarning("GLWidget constructor: exited");
      std::cout << "GLWidget constructor: exited" << endl;
      

      }

      // OpenGL initialization - called once at the beginning of the program
      // initialize shapes and specify OpenGL setting
      void GLWidget::initializeGL()
      {
      // Set this to true so GLEW knows to use a modern approach to retrieving
      // function pointers and extensions
      glewExperimental = true;
      // GLEW ininitialization - load the correct OpenGL functions
      GLenum err = glewInit(); // load the OpenGL extensions
      if ( err != GLEW_OK ) {
      // check for error
      std::cerr << "GLEW ERROR: " << glewGetErrorString(err);
      exit(1);
      }
      std::cout << "initializeGL: GLEW correctly initialized" << endl;

      // check if we can use sample buffers
      QSurfaceFormat format = QOpenGLWidget::format();
      if ( !format.samples() )
          std::cerr << "initializeGL: Could not enable sample buffers";
      
      // OpenGL state initialization
      glClearColor(128./255., 200./255., 255./255., 0.);
      glClearDepth(0.);
      glCullFace(GL_BACK);
      glEnable(GL_CULL_FACE);
      glEnable(GL_DEPTH_TEST);
      glDepthFunc(GL_GREATER);
      glReadBuffer(GL_BACK);
      //    glEnable(GL_FRAMEBUFFER_SRGB);
      // set the wireframe or fill polygon mode
      glPolygonMode(GL_FRONT_AND_BACK, polyMode);
      
      // debug
      std::cout << "initializeGL: GL initialized" << endl;
      
      // relative path to the vertex shader
      const GLchar * vShaderPath = "/Users/alessandromusi/Documents/workspace QT/hello_world3D_interaction_todo/shaders/basic.vsh";
      const GLchar * fShaderPath[2];
      // path to the (diffuse) fragment shader
      fShaderPath[0] = "/Users/alessandromusi/Documents/workspace QT/hello_world3D_interaction_todo/shaders/diffuse.fsh";
      // path to the (solid, no lights effects) fragment shader
      fShaderPath[1] = "/Users/alessandromusi/Documents/workspace QT/hello_world3D_interaction_todo/shaders/solid.fsh";
      // the program shader 0 uses the diffuse fragment shader
      ourShader[0] = new Shader( vShaderPath, fShaderPath[0] );
      // the program shader 1 uses the solid fragment shader
      ourShader[1] = new Shader( vShaderPath, fShaderPath[1] );
      
      // retrieve handles to uniform variables for the Shader program 0
      // (that using diffuse fragment shader)
      // vertex shader
      h_uProjMatrix[0] = glGetUniformLocation(ourShader[0]->programID, "uProjMatrix");
      h_uModelViewMatrix[0] = glGetUniformLocation(ourShader[0]->programID, "uModelViewMatrix");
      h_uNormalMatrix[0] = glGetUniformLocation(ourShader[0]->programID, "uNormalMatrix");
      // fragment shader
      h_uColor[0] = glGetUniformLocation(ourShader[0]->programID, "uColor");
      h_uLight1[0] = glGetUniformLocation(ourShader[0]->programID, "uLight");
      h_uLight2[0] = glGetUniformLocation(ourShader[0]->programID, "uLight2");
      
      // retrieve handles to uniform variables for the Shader program 1
      // (that using solid fragment shader)
      // vertex shader
      h_uProjMatrix[1] = glGetUniformLocation(ourShader[1]->programID, "uProjMatrix");
      h_uModelViewMatrix[1] = glGetUniformLocation(ourShader[1]->programID, "uModelViewMatrix");
      h_uNormalMatrix[1] = glGetUniformLocation(ourShader[1]->programID, "uNormalMatrix");
      // fragment shader
      h_uColor[1] = glGetUniformLocation(ourShader[1]->programID, "uColor");
      
      //    glBindFragDataLocation(h_fragColor, 0, "fragColor");
      
      // error checking
      const GLenum errCode = glGetError();
      if (errCode != GL_NO_ERROR) {
          cerr << "GL Error: " << errCode << endl;
      }
      
      // initialize the shape data
      initializeShape();
      

      }

      // drawing - called every time the screen should be updated
      void GLWidget::paintGL()
      {
      // clear color background color (light blue for the sky)
      // it is transparent
      glClearColor(128./255., 200./255., 255./255., 0.);
      // clear the buffer with the current clearing color
      glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

      // set the wireframe or fill polygon mode
      glPolygonMode(GL_FRONT_AND_BACK, polyMode);
      
      // use program shader
      if ( !activeShader )
          // set the shader 0 as the active one
          ourShader[0]->Use();
      else
          // set the shader 1 as the active one
          ourShader[1]->Use();
      
      // build & send projection matrix to vertex shader
      const Matrix4 projMatrix = makeProjectionMatrix();
      GLfloat glmatrix[16];
      projMatrix.writeToColumnMajorMatrix(glmatrix);
      // send projection matrix
      glUniformMatrix4fv(h_uProjMatrix[activeShader], 1, false, glmatrix);
      
      // change teh view point according to the user selection
      //Matrix4 eyeRbt;
      if ( viewMode == 0 )
          // use the skyRbt as the eyeRbt
          eyeRbt = skyRbt;
      else if ( viewMode == 1 )
          // use the frame of cube 1 (red cube)
          eyeRbt = objRbt[0];
      //eyeRbt = objRbt[0]*Matrix4::makeYRotation(-90);
      else if ( viewMode == 2 )
          // use the frame of cube 2 (blue cube)
          eyeRbt = objRbt[1];
      //eyeRbt = objRbt[1]*Matrix4::makeYRotation(90);
      
      // invert the eye frame matrix E-1
      const Matrix4 invEyeRbt = inv(eyeRbt);
      
      if ( !activeShader ) {
          // g_light1 position in eye coordinates
          const Cvec3 eyeLight1 = Cvec3(invEyeRbt * Cvec4(g_light1, 1));
          // g_light2 position in eye coordinates
          const Cvec3 eyeLight2 = Cvec3(invEyeRbt * Cvec4(g_light2, 1));
          // assign the uniform for the light
          glUniform3f(h_uLight1[activeShader], eyeLight1[0], eyeLight1[1], eyeLight1[2]);
          glUniform3f(h_uLight2[activeShader], eyeLight2[0], eyeLight2[1], eyeLight2[2]);
      }
      
      //////// draw FLOOR /////////////
      // set the floor Rbt matrix to the identity
      const Matrix4 groundRbt = Matrix4();
      Matrix4 MVM = invEyeRbt * groundRbt;
      Matrix4 NMVM = normalMatrix(MVM);
      GLfloat glmatrix1[16];
      // send MVM
      MVM.writeToColumnMajorMatrix(glmatrix1);
      glUniformMatrix4fv(h_uModelViewMatrix[activeShader], 1, false, glmatrix1);
      // send NMVM
      NMVM.writeToColumnMajorMatrix(glmatrix1);
      glUniformMatrix4fv(h_uNormalMatrix[activeShader], 1, false, glmatrix1);
      // set the floor color to green
      glUniform3f(h_uColor[activeShader], 0.1f, 0.95f, 0.1f);
      
      // draw floor
      glBindVertexArray(floorVAOID);
      glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
      glBindVertexArray(0);
      /////////////////////////////////
      
      //////// draw a red CUBE ////////
      // set the Rbt matrix of the cube to the identity
      //    Matrix4 objRbt = Matrix4::makeTranslation(Cvec3(0,0,0));
      MVM = invEyeRbt * objRbt[0];   // model view matrix E-1*O
      NMVM = normalMatrix(MVM);
      // linearize to a vector and send MVM
      MVM.writeToColumnMajorMatrix(glmatrix);
      glUniformMatrix4fv(h_uModelViewMatrix[activeShader], 1, false, glmatrix);
      // linearize to a vector and send NMVM
      NMVM.writeToColumnMajorMatrix(glmatrix);
      glUniformMatrix4fv(h_uNormalMatrix[activeShader], 1, false, glmatrix);
      // set the color of the cube object to red
      Cvec3f objColor = Cvec3f(1, 0, 0);
      glUniform3f(h_uColor[activeShader], objColor[0], objColor[1], objColor[2]);
      // draw cube
      glBindVertexArray(cubeVAOID);
      glDrawArrays(GL_TRIANGLES, 0, 36);
      glBindVertexArray(0);
      
      /////////////////////////////////
      
      //////// draw a blue CUBE ///////
      // set the Rbt matrix of the cube with a translation on the positive x
      //    objRbt = Matrix4::makeTranslation(Cvec3(2,0,0));
      // prima ruota e poi trasla
      //objRbt = Matrix4::makeTranslation(Cvec3(2,0,-1)) * Matrix4::makeYRotation(22.0);
      // prima trasla e po ruota
      //objRbt =  Matrix4::makeYRotation(22.0) * Matrix4::makeTranslation(Cvec3(2,0,-1));
      // prima scala e poi trasla
      //objRbt = Matrix4::makeTranslation(Cvec3(2,0,-1)) * Matrix4::makeScale(Cvec3(2,0.5,0.5));
      // prima trasla e poi scala
      //objRbt = Matrix4::makeScale(Cvec3(2,0.5,0.5)) * Matrix4::makeTranslation(Cvec3(2,0,-1));
      MVM = invEyeRbt * objRbt[1];   // E-1*O
      NMVM = normalMatrix(MVM);
      // linearize to a vector and send MVM
      MVM.writeToColumnMajorMatrix(glmatrix);
      glUniformMatrix4fv(h_uModelViewMatrix[activeShader], 1, false, glmatrix);
      // linearize to a vector and send NMVM
      NMVM.writeToColumnMajorMatrix(glmatrix);
      glUniformMatrix4fv(h_uNormalMatrix[activeShader], 1, false, glmatrix);
      // set the color of the cube object to blue
      objColor = Cvec3f(0, 0, 1);
      glUniform3f(h_uColor[activeShader], objColor[0], objColor[1], objColor[2]);
      // draw cube
      glBindVertexArray(cubeVAOID);
      glDrawArrays(GL_TRIANGLES, 0, 36);
      glBindVertexArray(0);
      
      /////////////////////////////////
      
      // debug
      std::cout << "paintGL: painted" << endl;
      

      }

      // resizing - called every time the widget is resized
      // The new size is passed in width and height
      void GLWidget::resizeGL( int w, int h )
      {
      // set the viewport to window dimensions
      // specifies the affine transformation of x and y from
      // normalized device coordinates to window coordinates
      glViewport( 0, 0, w, qMax( h, 1 ) );

      updateFrustFovY();
      // debug
      std::cout << "resizeGL: window resized w = " << w << " h = " << h << endl;
      

      }

      // initialize the shape (triangle data)
      void GLWidget::initializeShape()
      {
      GLfloat floor_size = 10.0f;
      GLfloat floor_y = -0.5f;
      // Set up vertex data (and buffer(s)) and attribute pointers
      GLfloat floor[] = {
      floor_size, floor_y, -floor_size, 0.0f, 1.0f, 0.0f, // Top Right
      floor_size, floor_y, floor_size, 0.0f, 1.0f, 0.0f, // Bottom Right
      -floor_size, floor_y, floor_size, 0.0f, 1.0f, 0.0f, // Bottom Left
      -floor_size, floor_y, -floor_size, 0.0f, 1.0f, 0.0f // Top Left
      };
      GLuint floorIdx[] = { // Note that we start from 0!
      0, 2, 1, // First Triangle
      0, 3, 2 // Second Triangle
      };

      GLfloat cube_size = 0.5f;
      // cube vertices and normal (36 vertices - six faces, each made
      // up of two triangles)
      GLfloat cube[] = {
          // bottom face
          -cube_size, -cube_size, -cube_size, 0.0f, -1.0f,  0.0f,
          cube_size, -cube_size,  cube_size, 0.0f, -1.0f,  0.0f,
          -cube_size, -cube_size,  cube_size, 0.0f, -1.0f,  0.0f,
          -cube_size, -cube_size, -cube_size, 0.0f, -1.0f,  0.0f,
          cube_size, -cube_size, -cube_size, 0.0f, -1.0f,  0.0f,
          cube_size, -cube_size,  cube_size, 0.0f, -1.0f,  0.0f,
          // right face
          cube_size, -cube_size,  cube_size, 1.0f,  0.0f,  0.0f,
          cube_size,  cube_size, -cube_size, 1.0f,  0.0f,  0.0f,
          cube_size,  cube_size,  cube_size, 1.0f,  0.0f,  0.0f,
          cube_size, -cube_size,  cube_size, 1.0f,  0.0f,  0.0f,
          cube_size, -cube_size, -cube_size, 1.0f,  0.0f,  0.0f,
          cube_size,  cube_size, -cube_size, 1.0f,  0.0f,  0.0f,
          // back face
          cube_size, -cube_size, -cube_size, 0.0f,  0.0f, -1.0f,
          -cube_size, -cube_size, -cube_size, 0.0f,  0.0f, -1.0f,
          cube_size,  cube_size, -cube_size, 0.0f,  0.0f, -1.0f,
          -cube_size, -cube_size, -cube_size, 0.0f,  0.0f, -1.0f,
          -cube_size,  cube_size, -cube_size, 0.0f,  0.0f, -1.0f,
          cube_size,  cube_size, -cube_size, 0.0f,  0.0f, -1.0f,
          // left face
          -cube_size, -cube_size, -cube_size, -1.0f,  0.0f,  0.0f,
          -cube_size, -cube_size,  cube_size, -1.0f,  0.0f,  0.0f,
          -cube_size,  cube_size, -cube_size, -1.0f,  0.0f,  0.0f,
          -cube_size, -cube_size,  cube_size, -1.0f,  0.0f,  0.0f,
          -cube_size,  cube_size,  cube_size, -1.0f,  0.0f,  0.0f,
          -cube_size,  cube_size, -cube_size, -1.0f,  0.0f,  0.0f,
          // front face
          -cube_size, -cube_size,  cube_size, 0.0f,  0.0f,  1.0f,
          cube_size, -cube_size,  cube_size, 0.0f,  0.0f,  1.0f,
          cube_size,  cube_size,  cube_size, 0.0f,  0.0f,  1.0f,
          -cube_size, -cube_size,  cube_size, 0.0f,  0.0f,  1.0f,
          cube_size,  cube_size,  cube_size, 0.0f,  0.0f,  1.0f,
          -cube_size,  cube_size,  cube_size, 0.0f,  0.0f,  1.0f,
          // top face
          -cube_size,  cube_size,  cube_size, 0.0f, 1.0f,  0.0f,
          cube_size,  cube_size,  cube_size, 0.0f, 1.0f,  0.0f,
          cube_size,  cube_size, -cube_size, 0.0f, 1.0f,  0.0f,
          -cube_size,  cube_size,  cube_size, 0.0f, 1.0f,  0.0f,
          cube_size,  cube_size, -cube_size, 0.0f, 1.0f,  0.0f,
          -cube_size,  cube_size, -cube_size, 0.0f, 1.0f,  0.0f
      };
      
      /////////// FLOOR //////////
      // create the VAO
      glGenVertexArrays(1, &floorVAOID);
      // create the VBO and eBO
      glGenBuffers(1, &floorVBOID);
      glGenBuffers(1, &floorEBOID);
      // Bind the VAO first, then bind and set vertex
      // buffer(s) and attribute pointer(s)
      glBindVertexArray(floorVAOID);
      // bind and pass data to the VBO
      glBindBuffer(GL_ARRAY_BUFFER, floorVBOID);
      glBufferData(GL_ARRAY_BUFFER, sizeof(floor), floor, GL_STATIC_DRAW);
      // bind and pass data to the EBO
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, floorEBOID);
      glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(floorIdx), floorIdx, GL_STATIC_DRAW);
      // set the position attribute
      glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (GLvoid*)0);
      glEnableVertexAttribArray(0);
      // set the normal attribute
      glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
      glEnableVertexAttribArray(1);
      // Unbind VAO (it's always a good thing to unbind any buffer/array
      // to prevent strange bugs)
      glBindBuffer(GL_ARRAY_BUFFER, 0);
      glBindVertexArray(0);
      
      /////////// CUBE //////////
      // cube vertices
      glGenVertexArrays(1, &cubeVAOID);
      glGenBuffers(1, &cubeVBOID);
      glBindVertexArray(cubeVAOID);
      glBindBuffer(GL_ARRAY_BUFFER, cubeVBOID);
      glBufferData(GL_ARRAY_BUFFER, sizeof(cube), cube, GL_STATIC_DRAW);
      // set the position attribute
      glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (GLvoid*)0);
      glEnableVertexAttribArray(0);
      // set the normal attribute
      glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
      glEnableVertexAttribArray(1);
      glBindBuffer(GL_ARRAY_BUFFER, 0);
      glBindVertexArray(0);
      

      }

      // initialize the shape (triangle data)
      void GLWidget::setRbtMatrix(Matrix4& m)
      {
      // set the object matrix (i.e., the matrix which express the
      // transformation to transfom the world frame into the object frame)
      if ( objMode == 0 )
      // apply the transformation to eye (camera) object
      //eyeRbt = m;
      skyRbt = m;
      else if ( objMode == 1 )
      // apply the transformation to cube 0
      objRbt[0] = m;
      else if ( objMode == 2 )
      // apply the transformation to cube 1
      objRbt[1] = m;

      // we always redraw if we changed the scene
      update();
      

      }

      // miscellaneous - overrides the behavior for the keyPressEvent
      // captures keyboard events
      void GLWidget::keyPressEvent( QKeyEvent* e )
      {
      // makes the application quit when the escape key is pressed
      switch ( e->key() ) {
      case Qt::Key_Escape:
      QCoreApplication::instance()->quit();
      std::cout << "ESC key pressed" << endl;
      break;
      case Qt::Key_H:
      cout << "\n ============== H E L P ==============\n\n"
      << "h\thelp menu\n"
      << "f\tToggle flat shading on/off\n"
      << "m\tToggle world-sky frame (sky view)\n"
      << "o\tCycle object to edit\n"
      << "s\tsave screenshot\n"
      << "v\tCycle view\n"
      << "w\tCycle fill/wireframe/point visualization\n"
      << "drag left mouse to rotate\n" << endl;
      break;
      case Qt::Key_F:
      // switch the fragment shader from solid to flat
      std::cout << "F key pressed" << endl;
      activeShader = (activeShader == 0) ? 1 : 0;
      break;
      case Qt::Key_M:
      // if the current object being modified is the sky camera (objMode==0),
      // and the eye is the sky camera (v), pressing ‘m’ should
      // switch between two frames for the auxiliary frame a
      // - World-sky frame: center at world’s origin and
      // axes aligned with sky camera
      // - Sky-sky frame: the sky camera’s frame
      mMode = (mMode == 0) ? 1 : 0;
      if (mMode == 0 )
      std::cout << "sky camera-sky camera mode" << endl;
      else
      std::cout << "world-sky camera mode" << endl;
      break;
      case Qt::Key_O:
      // cycles object to edit
      //std::cout << "O key pressed" << endl;
      objMode = (objMode+1)%3;
      if ( objMode == 0 )
      std::cout << "sky camera object selected" << endl;
      else if ( objMode == 1 )
      std::cout << "cube 1 object selected" << endl;
      else if ( objMode == 2 )
      std::cout << "cube 2 object selected" << endl;
      break;
      case Qt::Key_S:
      std::cout << "saving a screenshot of the scene";
      // force execution of GL commands in finite time
      glFlush();
      writePpmScreenshot(g_windowWidth, g_windowHeight, "out.ppm");
      break;
      case Qt::Key_V:
      //std::cout << "V key pressed (change the view)" << endl;
      viewMode = (viewMode+1)%3;
      if ( viewMode == 0 )
      std::cout << "view from the sky camera (default)" << endl;
      else if ( viewMode == 1 )
      std::cout << "view from cube 1 (red cube)" << endl;
      else if ( viewMode == 2 )
      std::cout << "view from cube 2 (blue cube)" << endl;
      break;
      case Qt::Key_W:
      // set a state variable and use it in paint
      //std::cerr << "W (wireframe) key pressed";
      if ( polyMode == GL_FILL ) {
      polyMode = GL_LINE;
      std::cout << "solid lines (wireframe)" << endl;
      }
      else if ( polyMode == GL_LINE ) {
      polyMode = GL_POINT;
      std::cout << "points" << endl;
      }
      else if ( polyMode == GL_POINT ) {
      polyMode = GL_FILL;
      std::cout << "fill (default)" << endl;
      }
      default:
      QOpenGLWidget::keyPressEvent( e );
      }
      update(); // see also repaint()
      }

      // simply records the position of the mouse when a button is initially pressed
      void GLWidget::mouseMoveEvent(QMouseEvent * event)
      {
      int dx = event->x() - lastPos.x();
      int dy = (g_windowHeight -1) - event->y() - lastPos.y(); // in Qt y=0 is at the top of the image
      //
      std::cout << "dx -> " << dx << " dy -> " << dy << endl;
      Matrix4 rbt;
      Matrix4 m;
      if ( objMode == 0 )
      rbt=skyRbt;
      else if ( objMode == 1 )
      rbt=objRbt[0];
      else if ( objMode == 2 )
      rbt=objRbt[1];
      if ( event->buttons() & Qt::LeftButton ) {
      // mouse left button down
      // rotate the object around x and y axis
      //da qui abbiamo usato la slide 25 moving with matrices
      Matrix4 Q= Matrix4::makeXRotation(-dy)*Matrix4::makeYRotation(dx);
      Matrix4 A=makeMixedFrame(rbt,eyeRbt);
      if(objMode==0){
      if(mMode==0)
      m=doQtoOwrtA(inv(Q),rbt,rbt);
      else{
      A=makeMixedFrame(Matrix4(),eyeRbt);//todo
      m=doQtoOwrtA(inv(Q),rbt,A);
      }
      }
      else
      m=doQtoOwrtA(Q,rbt,A);
      //Frame(rbt,eyeRbt);
      setRbtMatrix(m);
      std::cout << "left mouse button down" << endl;
      }
      else if ( event->buttons() & Qt::RightButton ) {
      // mouse right button down
      // translate the object left/right and up/down
      // TODO m matrix
      Matrix4 Q=Matrix4::makeTranslation(Cvec3(dx,dy,0)*0.01);
      Matrix4 A=makeMixedFrame(rbt,eyeRbt);
      if(objMode==0)
      if(mMode==0)
      m=doQtoOwrtA(inv(Q),rbt,rbt);
      else{
      A=makeMixedFrame(Matrix4(),eyeRbt);//todo
      m=doQtoOwrtA(inv(Q),rbt,A);
      }
      else
      m=doQtoOwrtA(Q,rbt,A);
      setRbtMatrix(m);
      std::cout << "right mouse button down" << endl;
      }
      else if ( event->buttons() & Qt::MidButton ) {
      // mouse middle button down or left and right button down
      // zoom in/out of the selected object
      Matrix4 Q=Matrix4::makeTranslation(Cvec3(0,0,-dy)*0.01);
      Matrix4 A=makeMixedFrame(rbt,eyeRbt);
      if(objMode==0)
      if(mMode==0)
      m=doQtoOwrtA(inv(Q),rbt,rbt);
      else{
      A=makeMixedFrame(Matrix4(),eyeRbt);//todo
      m=doQtoOwrtA(inv(Q),rbt,A);
      }
      else
      m=doQtoOwrtA(Q,rbt,A);
      setRbtMatrix(m);
      std::cout << "mid mouse button down" << endl;
      }
      // update the last position of the mouse
      lastPos = event->pos();
      lastPos.setY(g_windowHeight - lastPos.y() - 1);
      }

      // class destructor
      GLWidget::~GLWidget()
      {
      // Properly de-allocate all resources once they've outlived their purpose
      glDeleteVertexArrays(1, &floorVAOID);
      glDeleteVertexArrays(1, &cubeVAOID);

      glDeleteVertexArrays(1, &floorVBOID);
      glDeleteVertexArrays(1, &floorEBOID);
      glDeleteVertexArrays(1, &cubeVBOID);
      
      std::cout << "VBO and VAO released";
      

      }

      When I try to build i get this error:

      Undefined symbols for architecture x86_64:
      "GLWidget::mousePressEvent(QMouseEvent*)", referenced from:
      vtable for GLWidget in glwidget.o
      ld: symbol(s) not found for architecture x86_64
      clang: error: linker command failed with exit code 1 (use -v to see invocation)
      make: *** [hello_world3D_interaction_todo.app/Contents/MacOS/hello_world3D_interaction_todo] Error 1
      18:12:31: The process "/usr/bin/make" exited with code 2.
      Error while building/deploying project hello_world3D_interaction_todo (kit: Desktop Qt 5.5.1 clang 64bit)
      When executing step "Make"

      this is a screenshot of the compiler's option
      link text

      I have no clue what's the problem.

      1 Reply Last reply Reply Quote 0
      • SGaist
        SGaist Lifetime Qt Champion last edited by

        Hi and welcome to devnet,

        The error is that you don't have any implementation of mousePressEvent. Did you declare that function in GLWidget ?

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        ZakkWylde 1 Reply Last reply Reply Quote 0
        • ZakkWylde
          ZakkWylde @SGaist last edited by ZakkWylde

          @SGaist
          Hi, thanks for the reply
          here's the declaration in the header link text
          and here's the implementation in the .cpp file link text

          There real problem is that I've seen this very code perfectly working on other Mac, so this shouldn't be a coding problem.

          1 Reply Last reply Reply Quote 0
          • Paul Colby
            Paul Colby last edited by

            @ZakkWylde said:

            and here's the implementation in the .cpp file link text

            That image shows the implementation of mouseMoveEvent - not mousePressEvent.

            Your header is declaring both functions. Is your .cpp file implementing both? (Can't tell from the image)

            ZakkWylde 1 Reply Last reply Reply Quote 0
            • ZakkWylde
              ZakkWylde @Paul Colby last edited by

              @Paul-Colby Ok, I'm a total dumbass, the implementation of mousePressEvent was missing, I was probably confusing with mouseMoveEvent. I've added the implementation and it works just fine. Sorry for wasting your time.

              1 Reply Last reply Reply Quote 0
              • SGaist
                SGaist Lifetime Qt Champion last edited by

                No worries, things like that can happen ;)

                Since you have it working now, please mark the thread as solved using the "Topic Tool" button so that other forum users may know a solution has been found :)

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post