Undefined symbols for architecture x86_64
-
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 MBThis is the .pro file:
QT += core gui opengl
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = hello_world3D_interaction_todo
TEMPLATE = appSOURCES += main.cpp
glwidget.cpp
glew.c
ppm.cppHEADERS +=
glwidget.h
cvec.h
matrix4.h
shader.h
ppm.hFORMS += mainwindow.ui
DISTFILES +=
shaders/diffuse.fsh
shaders/solid.fsh
shaders/basic.vshunix:
INCLUDEPATH += /usr/local/include
DEPENDPATH += /usr/local/includethis 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 textI have no clue what's the problem.
-
Hi and welcome to devnet,
The error is that you don't have any implementation of mousePressEvent. Did you declare that function in GLWidget ?
-
Hi and welcome to devnet,
The error is that you don't have any implementation of mousePressEvent. Did you declare that function in GLWidget ?
-
@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 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)
@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.
-
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 :)