예제 #1
0
/*!
SLCamera::calcMinMax calculates the axis alligned minimum and maximum point of
the camera position and the 4 near clipping plane points.
*/
void SLCamera::calcMinMax(SLVec3f &minV, SLVec3f &maxV)
{
   SLScene* s = SLScene::current;
   SLSceneView* sv = s->activeSV();
   SLVec3f P[5];
   SLfloat aspect = (float)sv->scrW() / (float)sv->scrH();
   SLfloat tanFov = tan(_fov*SL_DEG2RAD*0.5f);
   SLfloat tN = tanFov * _clipNear; //top near
   SLfloat rN = tN * aspect;        //right near

   // frustum pyramid lines
   P[0].set(0,0,0);

   // around near clipping plane
   P[1].set( rN, tN,-_clipNear);
   P[2].set( rN,-tN,-_clipNear);
   P[3].set(-rN,-tN,-_clipNear);
   P[4].set(-rN, tN,-_clipNear);

   // init min & max points
   minV.set( FLT_MAX,  FLT_MAX,  FLT_MAX);
   maxV.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);

   // calc min and max point of all vertices
   for (SLuint i=0; i<5; ++i)
   {  if (P[i].x < minV.x) minV.x = P[i].x;
      if (P[i].x > maxV.x) maxV.x = P[i].x;
      if (P[i].y < minV.y) minV.y = P[i].y;
      if (P[i].y > maxV.y) maxV.y = P[i].y;
      if (P[i].z < minV.z) minV.z = P[i].z;
      if (P[i].z > maxV.z) maxV.z = P[i].z;
   }
}
예제 #2
0
/*! 
SLCamera::onDoubleTouch gets called whenever two fingers touch a handheld
screen.
*/
SLbool SLCamera::onTouch2Down(const SLint x1, const SLint y1,
                              const SLint x2, const SLint y2)
{	
   SLScene* s = SLScene::current;
   SLSceneView* sv = s->activeSV();
   
   // Determine the lookAt point by ray cast
   eyeToPixelRay((SLfloat)sv->scrWdiv2(), 
                 (SLfloat)sv->scrHdiv2(), &_lookAtRay);
   s->root3D()->hit(&_lookAtRay);
   
   _oldTouchPos1.set((SLfloat)x1, (SLfloat)y1);
   _oldTouchPos2.set((SLfloat)x2, (SLfloat)y2);
   return true;
}
예제 #3
0
/*! 
SLCamera::onMouseWheel event handler moves camera forwards or backwards
*/
SLbool SLCamera::onMouseWheel(const SLint delta, const SLKey mod)
{  
   SLScene* s = SLScene::current;
   SLSceneView* sv = s->activeSV();
   SLfloat sign = (SLfloat)SL_sign(delta);
   
   if (_camAnim==turntableYUp || _camAnim==turntableZUp) //....................
   {  if (mod==KeyNone)
      {  
         // Determine the lookAt point by ray cast
         eyeToPixelRay((SLfloat)sv->scrWdiv2(), 
                       (SLfloat)sv->scrHdiv2(), &_lookAtRay);
         s->root3D()->hit(&_lookAtRay);
         if (_lookAtRay.length < FLT_MAX) 
            _lookAtRay.hitPoint = _lookAtRay.origin + 
                                  _lookAtRay.dir*_lookAtRay.length;
         
         // Scale the mouse delta by the lookAt distance
         SLfloat lookAtDist;
         if (_lookAtRay.length < FLT_MAX && _lookAtRay.hitShape)
         {  lookAtDist = _lookAtRay.length;
         }
         else lookAtDist = _focalDist;
                  
         _vm.translation(_vm.m(12),_vm.m(13),_vm.m(14) + sign*lookAtDist*_dPos);
         _lookAtRay.length = FLT_MAX;
         setWMandState();
      }
      if (mod==KeyCtrl)
      {  _eyeSeparation *= (1.0f + sign*0.1f);
      }
      if (mod==KeyAlt)
      {  _fov += sign*5.0f;
         currentFOV = _fov;
      }
      if (mod==KeyShift)
      {  _focalDist *= (1.0f + sign*0.05f);
         
      }
      return true;
   }
   else if (_camAnim==walkingYUp || _camAnim==walkingZUp) //...................
   {  
      _speedLimit *= (1.0f + sign*0.1f);
   }
   return false;
}
예제 #4
0
//-----------------------------------------------------------------------------
//! Gets called whenever a mouse button gets pressed.
SLbool SLCamera::onMouseDown(const SLMouseButton button, 
                             const SLint x, const SLint y, const SLKey mod)
{  
   SLScene* s = SLScene::current;
   SLSceneView* sv = s->activeSV();
   
   // Determine the lookAt point by ray cast
   eyeToPixelRay((SLfloat)sv->scrWdiv2(), 
                 (SLfloat)sv->scrHdiv2(), &_lookAtRay);
   s->root3D()->hit(&_lookAtRay);
   
   // Init both position in case that the second finger came with delay
   _oldTouchPos1.set((SLfloat)x, (SLfloat)y);
   _oldTouchPos2.set((SLfloat)x, (SLfloat)y);
   
   return false;
}  
예제 #5
0
/*!
SLMaterial::activate applies the material parameter to the global render state
and activates the attached shader
*/
void SLMaterial::activate(SLGLState* state, SLShape* shape)
{      
   SLScene* s = SLScene::current;
   SLSceneView* sv = s->activeSV();

   // Deactivate shader program of the current active material
   if (current && current->shaderProg()) 
      current->shaderProg()->endShader();

   // Set this material as the current material
   current = this;

   // If no shader program is attached add the default shader program
   if (!_shaderProg)
   {  if (_textures.size()>0)
           shaderProg(s->shaderProgs(PerVrtBlinnTex));
      else shaderProg(s->shaderProgs(PerVrtBlinn));
   }

   // Check if shader had compile error and the error texture should be shown
   if (_shaderProg && _shaderProg->name().find("ErrorTex")!=string::npos)
   {  _textures.clear();
      _textures.push_back(new SLGLTexture("CompileError.png"));
   }
   
   // Set material in the state
   state->matAmbient    = _ambient;
   state->matDiffuse    = _diffuse;
   state->matSpecular   = _specular;
   state->matEmissive   = _emission;
   state->matShininess  = _shininess;
   
   // Determine use of shaders & textures
   SLbool useTexture = !(sv->drawBits()->get(SL_DB_TEXOFF) || 
                         shape->drawBits()->get(SL_DB_TEXOFF));
                            
   // Enable or disable texturing
   if (useTexture && _textures.size()>0)
   {  for (SLuint i=0; i<_textures.size(); ++i)
         _textures[i]->bindActive(i);
   }
    
   // Activate the shader program now
   shaderProg()->beginUse(this);
}
예제 #6
0
/*! This method is used for object picking. The calculation is the same as for
primary rays in Ray Tracing.
*/
void SLCamera::eyeToPixelRay(SLfloat x, SLfloat y, SLRay* ray)
{  
   SLScene* s = SLScene::current;
   SLSceneView* sv = s->activeSV();
   SLfloat  hw, hh, pixel; 
   SLVec3f  dir, EYE, LA, LU, LR, C, TL;
      
   // calculate half window width & height in world coords     
   hh = tan(SL_DEG2RAD*_fov/2); 
   hw = hh * sv->scrWdivH();

   // calculate the size of a pixel in world coords. 
   // height & width must be equal because perspective is undistorted.
   pixel = hw * 2 / sv->scrW();

   // get camera vectors
   _vm.lookAt(&EYE, &LA, &LU, &LR);

   // calculate a vector to the center (C) of the top left (TL) pixel
   C = LA;
   TL = C - hw*LR + hh*LU  +  pixel/2*LR - pixel/2*LU;

   // Calculate direction of ray
   dir = TL + pixel*x*LR - pixel*y*LU;
   
   // Fill in ray parameters
   dir.normalize();
   ray->origin.set(EYE);
   ray->setDir(dir);
   ray->length = FLT_MAX;
   ray->depth = 1;
   ray->contrib = 1.0f; 
   ray->type = PRIMARY;
   ray->x = x;
   ray->y = y;  
   ray->hitTriangle = 0;
   ray->hitMat = 0;
   ray->hitNormal.set(SLVec3f::ZERO);
   ray->hitPoint.set(SLVec3f::ZERO); 
   ray->originMat = &SLMaterial::AIR;
   ray->originTria = 0;
}
예제 #7
0
/*! 
SLCamera::onTouch2Move gets called whenever two fingers move on a handheld 
screen.
*/
SLbool SLCamera::onTouch2Move(const SLint x1, const SLint y1,
                              const SLint x2, const SLint y2)
{	
   SLScene* s = SLScene::current;
   SLSceneView* sv = s->activeSV();
   SLVec2f now1((SLfloat)x1, (SLfloat)y1);
   SLVec2f now2((SLfloat)x2, (SLfloat)y2);
   SLVec2f delta1(now1-_oldTouchPos1);
   SLVec2f delta2(now2-_oldTouchPos2);
   
   // Average out the deltas over the last 4 events for correct 1 pixel moves
   static SLuint  cnt=0;
   static SLVec2f d1[4];
   static SLVec2f d2[4];
   d1[cnt%4] = delta1;
   d2[cnt%4] = delta2;
   SLVec2f avgDelta1(d1[0].x+d1[1].x+d1[2].x+d1[3].x, d1[0].y+d1[1].y+d1[2].y+d1[3].y);
   SLVec2f avgDelta2(d2[0].x+d2[1].x+d2[2].x+d2[3].x, d2[0].y+d2[1].y+d2[2].y+d2[3].y);
   avgDelta1 /= 4.0f;
   avgDelta2 /= 4.0f;
   cnt++;
      
   SLfloat r1, phi1, r2, phi2;
   avgDelta1.toPolar(r1, phi1);
   avgDelta2.toPolar(r2, phi2);
    
   // 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();
   
   //SL_LOG("avgDelta1: (%05.2f,%05.2f), dPhi=%05.2f\n", avgDelta1.x, avgDelta1.y, SL_abs(phi1-phi2));
   
   // if fingers move parallel slide camera vertically or horizontally
   if (SL_abs(phi1-phi2) < 0.2f)
   {  
      // Calculate center between finger points
      SLVec2f nowCenter((now1+now2)*0.5f);
      SLVec2f oldCenter((_oldTouchPos1+_oldTouchPos2)*0.5f);
      
      // For first move set oldCenter = nowCenter
      if (oldCenter == SLVec2f::ZERO) oldCenter = nowCenter;
      
      SLVec2f delta(nowCenter - oldCenter);

      // scale to 0-1
      delta.x /= (SLfloat)sv->scrW();
      delta.y /= (SLfloat)sv->scrH();

      // scale to space size
      delta.x *= spaceW;
      delta.y *= spaceH;
      
      if (_camAnim==turntableYUp || _camAnim==turntableZUp)
      {           
         // apply delta to x- and y-position
         _vm.translation(_vm.m(12) + delta.x,
                         _vm.m(13) - delta.y,
                         _vm.m(14));

         setWMandState();
      } 
      else if (_camAnim == walkingYUp || _camAnim == walkingZUp)
      {
      	_maxSpeed.x = delta.x * 100.0f,
         _maxSpeed.z = delta.y * 100.0f;
      }

   } else // Two finger pinch
   {  
      // Calculate vector between fingers
      SLVec2f nowDist(now2 - now1);
      SLVec2f oldDist(_oldTouchPos2-_oldTouchPos1);
      
      // For first move set oldDist = nowDist
      if (oldDist == SLVec2f::ZERO) oldDist = nowDist;
      
      SLfloat delta = oldDist.length() - nowDist.length();

      if (_camAnim==turntableYUp)
      {  // scale to 0-1
         delta /= (SLfloat)sv->scrH();

         // scale to space height
         delta *= spaceH*2;
         
         // apply delta to the z-position
         _vm.translation(_vm.m(12),
                         _vm.m(13),
                         _vm.m(14) - delta);

         setWMandState();
      } 
      else if (_camAnim == walkingYUp)
      {  
         // change field of view
         _fov += SL_sign(delta) * 0.5f;
         currentFOV = _fov;
      }
   }

   _oldTouchPos1.set((SLfloat)x1, (SLfloat)y1);
   _oldTouchPos2.set((SLfloat)x2, (SLfloat)y2);
   return true;
}
예제 #8
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;
}