Beispiel #1
0
/*!
sets the rotation of this node. The axis parameter
will be transformed into 'relativeTo' space. So an passing in an axis
of (0, 1, 0) with TS_Object will rotate the node around its own up axis.
*/
void SLNode::rotation(const SLQuat4f& rot, 
                      SLTransformSpace relativeTo)
{   
    SLMat4f rotation = rot.toMat4(); 
    
    if (_parent && relativeTo == TS_world)
    {
        // get the inverse parent rotation to remove it from our current rotation
        // we want the input quaternion to absolutely set our new rotation relative 
        // to the world axes
        SLMat4f parentRotInv = _parent->updateAndGetWMI();
        parentRotInv.translation(0, 0, 0);
        
        // set the om rotation to the inverse of the parents rotation to achieve a
        // 0, 0, 0 relative rotation in world space
        _om.rotation(0, 0, 0, 0);
        _om *= parentRotInv;
        needUpdate();
        rotate(rot, relativeTo);
    }
    else if (relativeTo == TS_parent)
    {   // relative to parent, reset current rotation and just rotate again
        _om.rotation(0, 0, 0, 0);
        needUpdate();
        rotate(rot, relativeTo);
    }
    else
    {
        // in TS_Object everything is relative to our current orientation
        _om.rotation(0, 0, 0, 0);        
        _om *= rotation;
        needUpdate();
    }
}
Beispiel #2
0
/*!
SLCurveBezier::subdivideRender adds points along the curve to the point vector
renderPoints by recursively subdividing the curve with the Casteljau scheme.
*/
void SLCurveBezier::subdivideRender(SLVVec3f &renderPoints,
                                    const SLMat4f &wm,
                                    SLfloat epsilon,
                                    const SLVec3f& P0, const SLVec3f& P1, 
                                    const SLVec3f& P2, const SLVec3f& P3)
{
    // add first point transformed by wm if not already in the list
    if (renderPoints.size()==0)
        renderPoints.push_back(wm.multVec(P0));
    else if (P0 != renderPoints[renderPoints.size()-1])
        renderPoints.push_back(wm.multVec(P0));
   
    // check to see if basically straight
    SLfloat Lmin = P0.distance(P3);
    SLfloat Lmax = P0.distance(P1) + P1.distance(P2) + P2.distance(P3);
    SLfloat diff = Lmin - Lmax;
    if (diff*diff < epsilon) return;

    // otherwise get control points for subdivision
    SLVec3f L1  = (P0 + P1) * 0.5f;
    SLVec3f H   = (P1 + P2) * 0.5f;
    SLVec3f L2  = (L1 + H)  * 0.5f;
    SLVec3f R2  = (P2 + P3) * 0.5f;
    SLVec3f R1  = (H  + R2) * 0.5f;
    SLVec3f mid = (L2 + R1) * 0.5f;

    // subdivide
    subdivideRender(renderPoints, wm, epsilon, P0, L1, L2, mid);
    subdivideRender(renderPoints, wm, epsilon, mid, R1, R2, P3);
}
/*! Scans all meshes in the assimp scene and populates nameToBone and
jointGroups
*/
void SLAssimpImporter::findJoints(const aiScene* scene)
{
    for (SLuint i = 0; i < scene->mNumMeshes; i++)
    {
        aiMesh* mesh = scene->mMeshes[i];
        if(!mesh->HasBones())
            continue;

		logMessage(LV_normal, "   Mesh '%s' contains %d joints.\n", mesh->mName.C_Str(), mesh->mNumBones);
        
        for (SLuint j = 0; j < mesh->mNumBones; j++)
        {
			SLstring name = mesh->mBones[j]->mName.C_Str();
            std::map<SLstring, SLMat4f>::iterator it = _jointOffsets.find(name);
			if(it != _jointOffsets.end())
				continue;

            // add the offset matrix to our offset matrix map
			SLMat4f offsetMat;
			memcpy(&offsetMat, &mesh->mBones[j]->mOffsetMatrix, sizeof(SLMat4f));
			offsetMat.transpose();
			_jointOffsets[name] = offsetMat;


			logMessage(LV_detailed, "     Bone '%s' found.\n", name.c_str());
        }
    }
}
Beispiel #4
0
/*!
Rotates the node around its local origin relative to the space expressed by 'relativeTo'.
*/
void SLNode::rotate(const SLQuat4f& rot, SLTransformSpace relativeTo)
{
    SLQuat4f norm = rot.normalized();
    SLMat4f rotation = rot.toMat4();


    if (relativeTo == TS_object)
    {
        _om *= rotation;
    }
    else if (_parent && relativeTo == TS_world)
    {
        SLMat4f rot;
        rot.translate(updateAndGetWM().translation());
        rot.multiply(rotation);
        rot.translate(-updateAndGetWM().translation());

        _om = _parent->_wm.inverse() * rot * updateAndGetWM();
    }
    else // relativeTo == TS_Parent || relativeTo == TS_World && !_parent
    {
        SLMat4f rot;
        rot.translate(translation());
        rot.multiply(rotation);
        rot.translate(-translation());

        _om.setMatrix(rot * _om);
    }

    needUpdate();
}
/*!
onResize: Event handler called on the resize event of the window. This event
should called once before the onPaint event. Do everything that is dependent on
the size and ratio of the window.
*/
void onResize(GLFWwindow* window, int width, int height)
{  
    double w = (double)width;
    double h = (double)height;

    // define the projection matrix
    _projectionMatrix.perspective(45, w/h, 0.01f, 10.0f);

    // define the viewport
    glViewport(0, 0, width, height);

    onPaint();
}
Beispiel #6
0
/*!
Applies the view transform to the modelview matrix depending on the eye:
eye=-1 for left, eye=1 for right
*/
void SLCamera::setView(const SLEye eye)
{  
   SLSceneView* sv = SLScene::current->activeSV();
   
   if (eye == centerEye)
   {  stateGL->modelViewMatrix.identity();
      stateGL->modelViewMatrix.multiply(_vm); 
   } 
   else // stereo viewing
   {
      if (_projection == stereoSideBySideD)
      {  
         // half interpupilar distance
         _eyeSeparation = sv->oculus()->eyeSeparation();
         SLfloat halfIPD = (SLfloat)eye * _eyeSeparation * -0.5f;

         // get the oculus orientation
         SLMat4f rotation(sv->oculus()->orientation().toMat4());
         SLMat4f vmEye(SLMat4f(halfIPD, 0.0f, 0.f) * rotation * _vm);
         stateGL->modelViewMatrix = vmEye;
         stateGL->viewMatrix = vmEye;
      }
      else
      {
         // Get central camera vectors eye, lookAt, lookUp out of the view matrix vm
         SLVec3f EYE, LA, LU, LR;
         _vm.lookAt(&EYE, &LA, &LU, &LR);
   
         // Shorten LR to half of the eye dist (eye=-1 for left, eye=1 for right)
         LR *= _eyeSeparation * 0.5f * (SLfloat)eye;
      
         // Set the OpenGL view matrix for the left eye
         SLMat4f vmEye;
         vmEye.lookAt(EYE+LR, EYE + _focalDist*LA+LR, LU);
         stateGL->modelViewMatrix = vmEye;
         stateGL->viewMatrix = vmEye;
      }
   } 
}
Beispiel #7
0
/*!
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();
}
Beispiel #8
0
//-----------------------------------------------------------------------------
//! 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;
}
Beispiel #9
0
/*!
Applies the view transform to the modelview matrix depending on the eye:
eye=-1 for left, eye=1 for right
*/
void SLCamera::setView(SLSceneView* sv, const SLEye eye)
{  
    SLScene* s = SLScene::current;
   
    SLMat4f vm = updateAndGetWMI();

    if (eye == centerEye)
    {   _stateGL->modelViewMatrix.identity();
        _stateGL->viewMatrix.setMatrix(vm);
    } 
    else // stereo viewing
    {
        if (_projection == stereoSideBySideD)
        {  
            // half interpupilar disqtance
            //_eyeSeparation = s->oculus()->interpupillaryDistance(); update old rift code
            SLfloat halfIPD = (SLfloat)eye * _eyeSeparation * -0.5f;
            
            SLMat4f trackingPos;
            if (_useDeviceRot)
            {
                // get the oculus or mobile device orientation
                SLQuat4f rotation;
                if (s->oculus()->isConnected())
                {
                    rotation = s->oculus()->orientation(eye);
                    trackingPos.translate(-s->oculus()->position(eye));
                }
                else rotation = sv->deviceRotation();

                SLfloat rotX, rotY, rotZ;
                rotation.toMat4().toEulerAnglesZYX(rotZ, rotY, rotX);
                //SL_LOG("rotx : %3.1f, roty: %3.1f, rotz: %3.1f\n", rotX*SL_RAD2DEG, rotY*SL_RAD2DEG, rotZ*SL_RAD2DEG);
                SLVec3f viewAdjust = s->oculus()->viewAdjust(eye) * _unitScaling;
                SLMat4f vmEye(SLMat4f(viewAdjust.x, viewAdjust.y, viewAdjust.z) * rotation.inverted().toMat4() * trackingPos * vm);
                _stateGL->modelViewMatrix = vmEye;
                _stateGL->viewMatrix = vmEye;
            } 
            else
            {      
                SLMat4f vmEye(SLMat4f(halfIPD, 0.0f, 0.f) * vm);
                _stateGL->modelViewMatrix = vmEye;
                _stateGL->viewMatrix = vmEye;
            }
        }
        else
        {
            // Get central camera vectors eye, lookAt, lookUp out of the view matrix vm
            SLVec3f EYE, LA, LU, LR;
            vm.lookAt(&EYE, &LA, &LU, &LR);
   
            // Shorten LR to half of the eye dist (eye=-1 for left, eye=1 for right)
            LR *= _eyeSeparation * 0.5f * (SLfloat)eye;
      
            // Set the OpenGL view matrix for the left eye
            SLMat4f vmEye;
            vmEye.lookAt(EYE+LR, EYE + _focalDist*LA+LR, LU);
            _stateGL->modelViewMatrix = vmEye;
            _stateGL->viewMatrix = vmEye;
        }
    } 
}
Beispiel #10
0
/*!
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;
}
Beispiel #11
0
/*! 
SLCurveBezier::draw does the OpenGL rendering of the Bezier curve in world 
space.
*/
void SLCurveBezier::draw(const SLMat4f &wm)
{  
    SLint numControlPoints = 2*((SLint)_points.size()-1);

    // Create buffer object
    if (!_vao.id())
    {  
        // Build renderPoints by recursively subdividing the curve
        SLVVec3f renderPoints;
        for (SLuint i = 0; i < _points.size()-1; ++i)
        {   subdivideRender(renderPoints, wm, 0.00001f, 
                            _points[i].vec3(), _controls[2*i], 
                            _controls[2*i+1], _points[i+1].vec3());
        }
   
        // add last point to the curve vector
        renderPoints.push_back(wm.multVec(_points[_points.size()-1].vec3()));

        // add inputs points
        for (SLuint i = 0; i < _points.size(); ++i)
            renderPoints.push_back(wm.multVec(_points[i].vec3()));
      
        // add control points
        for (SLint i = 0; i < numControlPoints; ++i)
            renderPoints.push_back(wm.multVec(_controls[i]));

        // add tangent points
        for (SLint i = 0; i < numControlPoints; ++i)
        {   renderPoints.push_back(wm.multVec(_controls[i]));
            int iPoint = (SLint)((SLfloat)i/2.0f + 0.5f);
            renderPoints.push_back(wm.multVec(_points[iPoint].vec3()));
        }
      
        // Generate finally the OpenGL rendering buffer
        _vao.generateVertexPos(&renderPoints);
    }
   
    if (!_vao.id()) return;

    // Set the view transform
    SLGLState* stateGL = SLGLState::getInstance();
    stateGL->modelViewMatrix.setMatrix(stateGL->viewMatrix);

    SLint numTangentPoints = numControlPoints * 2;
    SLint numCurvePoints = _vao.numVertices() -
                           (SLint)_points.size() - numControlPoints - numTangentPoints;
   
    // Draw curve as a line strip through interpolated points
    _vao.drawArrayAsColored(PT_lineStrip, SLCol3f::RED, 1, 0, numCurvePoints);
   
    // ES2 has often problems with rendering points
    #ifndef SL_GLES2
    // Draw curve as a line strip through interpolated points
    _vao.drawArrayAsColored(PT_points, SLCol4f::RED, 3, 0, numCurvePoints);

    // Draw input points
    _vao.drawArrayAsColored(PT_points, SLCol4f::BLUE, 6, 
                            numCurvePoints, (SLuint)_points.size());

    // Draw control points
    _vao.drawArrayAsColored(PT_points, SLCol4f::YELLOW, 6,
                            numCurvePoints + (SLuint)_points.size(), 
                            numControlPoints);

    // Draw tangent points as lines
    _vao.drawArrayAsColored(PT_lines, SLCol4f::YELLOW, 1,
                            numCurvePoints + (SLint)_points.size() + numControlPoints, 
                            numTangentPoints);
    #endif
}
Beispiel #12
0
//-----------------------------------------------------------------------------
//! 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;
}