/*! Rotates the node around an arbitrary point. The 'axis' and 'point' parameter are relative to the space described by 'relativeTo'. */ void SLNode::rotateAround(const SLVec3f& point, SLVec3f& axis, SLfloat angleDeg, SLTransformSpace relativeTo) { SLVec3f localPoint = point; SLVec3f localAxis = axis; if (relativeTo == TS_world && _parent) { localPoint = _parent->updateAndGetWMI() * point; localAxis = _parent->updateAndGetWMI().mat3() * axis; } SLMat4f rot; rot.translate(localPoint); rot.rotate(angleDeg, localAxis); rot.translate(-localPoint); if (relativeTo == TS_object) _om.setMatrix(_om * rot); else _om.setMatrix(rot * _om); needUpdate(); }
//----------------------------------------------------------------------------- //! Gets called whenever the mouse is moved. SLbool SLCamera::onMouseMove(const SLMouseButton button, const SLint x, const SLint y, const SLKey mod) { if (button == ButtonLeft) //================================================ { // new vars needed SLVec3f position = this->translation(); SLVec3f forward = this->forward(); SLVec3f right = this->right(); SLVec3f up = this->up(); // The lookAt point SLVec3f laP = position + _focalDist * forward; // Determine rotation point as the center of the AABB of the hitNode SLVec3f rtP; if (_lookAtRay.length < FLT_MAX && _lookAtRay.hitNode) rtP = _lookAtRay.hitNode->aabb()->centerWS(); else rtP = laP; // Determine rot angles around x- & y-axis SLfloat dY = (y-_oldTouchPos1.y) * _rotFactor; SLfloat dX = (x-_oldTouchPos1.x) * _rotFactor; if (_camAnim==turntableYUp) //....................................... { SLMat4f rot; rot.translate(rtP); rot.rotate(-dX, SLVec3f(0,1,0)); rot.rotate(-dY, right); rot.translate(-rtP); _om.setMatrix(rot * _om); needWMUpdate(); } else if (_camAnim==turntableZUp) //.................................. { SLMat4f rot; rot.translate(rtP); rot.rotate(dX, SLVec3f(0,0,1)); rot.rotate(dY, right); rot.translate(-rtP); _om.setMatrix(rot * _om); needWMUpdate(); } else if (_camAnim==walkingYUp) //.................................... { dY *= 0.5f; dX *= 0.5f; SLMat4f rot; rot.rotate(-dX, SLVec3f(0, 1, 0)); rot.rotate(-dY, right); forward.set(rot.multVec(forward)); lookAt(position + forward); } else if (_camAnim==walkingZUp) //.................................... { dY *= 0.5f; dX *= 0.5f; SLMat4f rot; rot.rotate(-dX, SLVec3f(0, 0, 1)); rot.rotate(-dY, right); forward.set(rot.multVec(forward)); lookAt(position + forward, SLVec3f(0, 0, 1)); } _oldTouchPos1.set((SLfloat)x,(SLfloat)y); } else if (button == ButtonMiddle) //============================================== { if (_camAnim==turntableYUp || _camAnim==turntableZUp) { // Calculate the fraction delta of the mouse movement SLVec2f dMouse(x-_oldTouchPos1.x, _oldTouchPos1.y-y); dMouse.x /= (SLfloat)_scrW; dMouse.y /= (SLfloat)_scrH; // Scale the mouse delta by the lookAt distance SLfloat lookAtDist; if (_lookAtRay.length < FLT_MAX) lookAtDist = _lookAtRay.length; else lookAtDist = _focalDist; // scale factor depending on the space sice at focal dist SLfloat spaceH = tan(SL_DEG2RAD*_fov/2) * lookAtDist * 2.0f; SLfloat spaceW = spaceH * _aspect; dMouse.x *= spaceW; dMouse.y *= spaceH; if (mod==KeyCtrl) { translate(SLVec3f(-dMouse.x, 0, dMouse.y), TS_Object); } else { translate(SLVec3f(-dMouse.x, -dMouse.y, 0), TS_Object); } _oldTouchPos1.set((SLfloat)x,(SLfloat)y); } } //======================================================================== return true; }
/*! onPaint does all the rendering for one frame from scratch with OpenGL (in core profile). */ bool onPaint() { // Clear the color & depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // View transform: move the coordinate system away from the camera _viewMatrix.identity(); _viewMatrix.translate(0, 0, _camZ); // View transform: rotate the coordinate system increasingly by the mouse _viewMatrix.rotate(_rotX + _deltaX, 1,0,0); _viewMatrix.rotate(_rotY + _deltaY, 0,1,0); // Transform light position & direction into view space SLVec3f lightPosVS = _viewMatrix * _lightPos; // The light dir is not a position. We only take the rotation of the mv matrix. SLMat3f viewRot = _viewMatrix.mat3(); SLVec3f lightDirVS = viewRot * _lightDir; // Rotate the model so that we see the square from the front side // or the earth from the equator. _modelMatrix.identity(); _modelMatrix.rotate(90, -1,0,0); // Build the combined model-view and model-view-projection matrix SLMat4f mvp(_projectionMatrix); SLMat4f mv(_viewMatrix * _modelMatrix); mvp.multiply(mv); // Build normal matrix SLMat3f nm(mv.inverseTransposed()); // Pass the matrix uniform variables glUniformMatrix4fv(_mvMatrixLoc, 1, 0, (float*)&mv); glUniformMatrix3fv(_nMatrixLoc, 1, 0, (float*)&nm); glUniformMatrix4fv(_mvpMatrixLoc, 1, 0, (float*)&mvp); // Pass lighting uniforms variables glUniform4fv(_globalAmbiLoc, 1, (float*)&_globalAmbi); glUniform3fv(_lightPosVSLoc, 1, (float*)&lightPosVS); glUniform3fv(_lightDirVSLoc, 1, (float*)&lightDirVS); glUniform4fv(_lightAmbientLoc, 1, (float*)&_lightAmbient); glUniform4fv(_lightDiffuseLoc, 1, (float*)&_lightDiffuse); glUniform4fv(_lightSpecularLoc, 1, (float*)&_lightSpecular); glUniform4fv(_matAmbientLoc, 1, (float*)&_matAmbient); glUniform4fv(_matDiffuseLoc, 1, (float*)&_matDiffuse); glUniform4fv(_matSpecularLoc, 1, (float*)&_matSpecular); glUniform4fv(_matEmissiveLoc, 1, (float*)&_matEmissive); glUniform1f (_matShininessLoc, _matShininess); glUniform1i (_texture0Loc, 0); ////////////////////// // Draw with 2 VBOs // ////////////////////// // Enable all of the vertex attribute arrays glEnableVertexAttribArray(_pLoc); glEnableVertexAttribArray(_nLoc); glEnableVertexAttribArray(_tLoc); // Activate VBOs glBindBuffer(GL_ARRAY_BUFFER, _vboV); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboI); // Activate Texture glBindTexture(GL_TEXTURE_2D, _textureID); // For VBO only offset instead of data pointer GLsizei stride = sizeof(VertexPNT); GLsizei offsetN = sizeof(SLVec3f); GLsizei offsetT = sizeof(SLVec3f) + sizeof(SLVec3f); glVertexAttribPointer(_pLoc, 3, GL_FLOAT, GL_FALSE, stride, 0); glVertexAttribPointer(_nLoc, 3, GL_FLOAT, GL_FALSE, stride, (void*)offsetN); glVertexAttribPointer(_tLoc, 2, GL_FLOAT, GL_FALSE, stride, (void*)offsetT); //////////////////////////////////////////////////////// // Draw cube model triangles by indexes glDrawElements(GL_TRIANGLES, _numI, GL_UNSIGNED_INT, 0); //////////////////////////////////////////////////////// // Deactivate buffers glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // Disable the vertex arrays glDisableVertexAttribArray(_pLoc); glDisableVertexAttribArray(_nLoc); glDisableVertexAttribArray(_tLoc); // Check for errors from time to time GETGLERROR; // Fast copy the back buffer to the front buffer. This is OS dependent. glfwSwapBuffers(window); // Calculate frames per second char title[255]; static float lastTimeSec = 0; float timeNowSec = (float)glfwGetTime(); float fps = calcFPS(timeNowSec-lastTimeSec); sprintf(title, "Sphere, %d x %d, fps: %4.0f", _resolution, _resolution, fps); glfwSetWindowTitle(window, title); lastTimeSec = timeNowSec; // Return true to get an immediate refresh return true; }
//----------------------------------------------------------------------------- //! Gets called whenever the mouse is moved. SLbool SLCamera::onMouseMove(const SLMouseButton button, const SLint x, const SLint y, const SLKey mod) { SLScene* s = SLScene::current; SLSceneView* sv = s->activeSV(); if (button == ButtonLeft) //================================================ { // Get camera vectors: eye pos., lookAt, lookUp, lookRight SLVec3f eye, LA, LU, LR; _vm.lookAt(&eye, &LA, &LU, &LR); // The lookAt and lookUp point in VS SLVec3f laP = eye + _focalDist * LA; // Determine rotation point as the center of the AABB of the hitShape SLVec3f rtP; if (_lookAtRay.length < FLT_MAX && _lookAtRay.hitShape) rtP = _lookAtRay.hitShape->aabb()->centerWS(); else rtP = laP; // Determine rot angles around x- & y-axis SLfloat dY = (_oldTouchPos1.y-y) * _rotFactor; SLfloat dX = (_oldTouchPos1.x-x) * _rotFactor; if (_camAnim==turntableYUp) //....................................... { // Apply rotation around the lookAt point SLMat4f rot; rot.translate(rtP); rot.rotate(-dY, LR); rot.rotate(-dX, SLVec3f(0,1,0)); rot.translate(-rtP); _vm *= rot; } else if (_camAnim==turntableZUp) //.................................. { // Apply rotation around the lookAt point SLMat4f rot; rot.translate(rtP); rot.rotate(-dY, LR); rot.rotate(-dX, SLVec3f(0,0,1)); rot.translate(-rtP); _vm *= rot; } else if (_camAnim==walkingYUp) //.................................... { dY *= 0.5f; dX *= 0.5f; // Apply rotation around the lookRight and the Y-axis SLMat4f rot; rot.rotate(-dY, LR); rot.rotate(-dX, SLVec3f(0,1,0)); // rotate eye position LA.set(rot*LA); _vm.lookAt(eye, eye+LA*_focalDist, SLVec3f(0,1,0)); } else if (_camAnim==walkingZUp) //.................................... { dY *= 0.5f; dX *= 0.5f; // Apply rotation around the lookRight and the Z-axis SLMat4f rot; rot.rotate(-dY, LR); rot.rotate(-dX, SLVec3f(0,0,1)); // rotate eye position LA.set(rot*LA); _vm.lookAt(eye, eye+LA*_focalDist, SLVec3f(0,0,1)); } setWMandState(); _oldTouchPos1.set((SLfloat)x,(SLfloat)y); return true; } else if (button == ButtonMiddle) //============================================== { if (_camAnim==turntableYUp || _camAnim==turntableZUp) { // Calculate the fraction delta of the mouse movement SLVec2f dMouse(x-_oldTouchPos1.x, _oldTouchPos1.y-y); dMouse.x /= (SLfloat)sv->scrW(); dMouse.y /= (SLfloat)sv->scrH(); // Scale the mouse delta by the lookAt distance SLfloat lookAtDist; if (_lookAtRay.length < FLT_MAX) lookAtDist = _lookAtRay.length; else lookAtDist = _focalDist; // scale factor depending on the space sice at focal dist SLfloat spaceH = tan(SL_DEG2RAD*_fov/2) * lookAtDist * 2.0f; SLfloat spaceW = spaceH * sv->scrWdivH(); dMouse.x *= spaceW; dMouse.y *= spaceH; if (mod==KeyCtrl) { _vm.translation(_vm.m(12) + dMouse.x, _vm.m(13), _vm.m(14) + dMouse.y); } else { _vm.translation(_vm.m(12) + dMouse.x, _vm.m(13) + dMouse.y, _vm.m(14)); } setWMandState(); _oldTouchPos1.set((SLfloat)x,(SLfloat)y); return true; } } //======================================================================== return false; }