Ejemplo n.º 1
0
F32
afxEase::eq(F32 t, F32 a, F32 b, F32 ein, F32 eout)
{
  if (t == 0.0)
    return a;
  
  if (t == 1.0)
    return b;
  
  F32 ab = b - a;
  F32 ee = eout - ein + 1.0;
  
  // ease in section
  if (t <= ein)
  {
    F32 tin = t/ein;
    return a + (mSin(M_PI_F*(tin - 1.0)) + M_PI_F*tin)*ab*ein*(1.0/M_PI_F)/ee;
  }

  // middle linear section
  else if (t <= eout)
  {
    return a + ab*(2.0*t - ein)/ee;
  }

  // ease out section
  else 
  {
    F32 iout = 1.0 - eout;
    F32 g	= (t - eout)*M_PI_F/iout;
    return ((mSin(g) + g)*(iout)/M_PI_F + 2.0*eout - ein)*ab/ee + a;
  }
}
Ejemplo n.º 2
0
F32
afxEase::t(F32 t, F32 ein, F32 eout)
{
  if (t == 0.0)
    return 0.0;
  
  if (t == 1.0)
    return 1.0;
  
  F32 ee = eout - ein + 1.0;
  
  // ease in section
  if (t <= ein)
  {
    F32 tin = t/ein;
    return (mSin(M_PI_F*(tin - 1.0)) + M_PI_F*tin)*ein*(1.0/M_PI_F)/ee;
  }

  // middle linear section
  else if (t <= eout)
  {
    return (2.0*t - ein)/ee;
  }

  // ease out section
  else 
  {
    F32 iout = 1.0 - eout;
    F32 g	= (t - eout)*M_PI_F/iout;
    return ((mSin(g) + g)*(iout)/M_PI_F + 2.0*eout - ein)*1.0/ee + 0.0;
  }
}
Ejemplo n.º 3
0
void PaintMaterialAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type)
{
   S32 mat = mTerrainEditor->getPaintMaterialIndex();
   if ( !selChanged || mat < 0 )
      return;

   const bool slopeLimit = mTerrainEditor->mSlopeMinAngle > 0.0f || mTerrainEditor->mSlopeMaxAngle < 90.0f;
   const F32 minSlope = mSin( mDegToRad( 90.0f - mTerrainEditor->mSlopeMinAngle ) );
   const F32 maxSlope = mSin( mDegToRad( 90.0f - mTerrainEditor->mSlopeMaxAngle ) );

   const TerrainBlock *terrain = mTerrainEditor->getActiveTerrain();
   const F32 squareSize = terrain->getSquareSize();

   Point2F p;
   Point3F norm;


   for( U32 i = 0; i < sel->size(); i++ )
   {
      GridInfo &inf = (*sel)[i];

      if ( slopeLimit )
      {
         p.x = inf.mGridPoint.gridPos.x * squareSize;
         p.y = inf.mGridPoint.gridPos.y * squareSize;
         if ( !terrain->getNormal( p, &norm, true ) )
            continue;

         if (  norm.z > minSlope ||
               norm.z < maxSlope )
            continue;  
      }

      // If grid is already set to our material, or it is an
      // empty grid spot, then skip painting.
      if ( inf.mMaterial == mat || inf.mMaterial == U8_MAX )
         continue;

      if ( mRandF() > mTerrainEditor->getBrushPressure() )
         continue;

      inf.mMaterialChanged = true;
      mTerrainEditor->getUndoSel()->add(inf);

      // Painting is really simple now... set the one mat index.
      inf.mMaterial = mat;
      mTerrainEditor->setGridInfo(inf, true);
   }

   mTerrainEditor->scheduleMaterialUpdate();
}
Ejemplo n.º 4
0
bool AITurretShape::onNewDataBlock(GameBaseData* dptr, bool reload)
{
   mDataBlock = dynamic_cast<AITurretShapeData*>(dptr);
   if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload))
      return false;

   mScanHeading = mDegToRad(mDataBlock->maxScanHeading);
   if (mIsZero(mScanHeading))
      mScanHeading = M_PI_F;
   mScanPitch = mDegToRad(mDataBlock->maxScanPitch);
   if (mIsZero(mScanPitch))
      mScanPitch = M_PI_F;

   mScanDistance = mDataBlock->maxScanDistance;
   mScanDistanceSquared = mScanDistance * mScanDistance;

   mWeaponRangeSquared = mDataBlock->maxWeaponRange * mDataBlock->maxWeaponRange;
   mWeaponLeadVelocitySquared = (mDataBlock->weaponLeadVelocity > 0) ? (mDataBlock->weaponLeadVelocity * mDataBlock->weaponLeadVelocity) : 0;

   // The scan box is built such that the scanning origin is at (0,0,0) and the scanning distance
   // is out along the y axis.  When this is transformed to the turret's location is provides a
   // scanning volume in front of the turret.
   F32 scanX = mScanDistance*mSin(mScanHeading);
   F32 scanY = mScanDistance;
   F32 scanZ = mScanDistance*mSin(mScanPitch);
   mScanBox.set(-scanX, 0, -scanZ, scanX, scanY, scanZ);

   mScanTickFrequency = mDataBlock->scanTickFrequency;
   if (mScanTickFrequency < 1)
      mScanTickFrequency = 1;

   mScanTickFrequencyVariance = mDataBlock->scanTickFrequencyVariance;
   if (mScanTickFrequencyVariance < 0)
      mScanTickFrequencyVariance = 0;

   mTicksToNextScan = mScanTickFrequency;

   // For states
   mStateAnimThread = 0;
   if (mDataBlock->isAnimated)
   {
      mStateAnimThread = mShapeInstance->addThread();
      mShapeInstance->setTimeScale(mStateAnimThread,0);
   }

   scriptOnNewDataBlock();
   return true;
}
Ejemplo n.º 5
0
QuatF & QuatF::interpolate( const QuatF & q1, const QuatF & q2, F32 t )
{
   //-----------------------------------
   // Calculate the cosine of the angle:

   double cosOmega = q1.dot( q2 );

   //-----------------------------------
   // adjust signs if necessary:

   F32 sign2;
   if ( cosOmega < 0.0 )
   {
      cosOmega = -cosOmega;
      sign2 = -1.0f;
   }
   else
      sign2 = 1.0f;

   //-----------------------------------
   // calculate interpolating coeffs:

   double scale1, scale2;
   if ( (1.0 - cosOmega) > 0.00001 )
   {
      // standard case
      double omega = mAcos(cosOmega);
      double sinOmega = mSin(omega);
      scale1 = mSin((1.0 - t) * omega) / sinOmega;
      scale2 = sign2 * mSin(t * omega) / sinOmega;
   }
   else
   {
      // if quats are very close, just do linear interpolation
      scale1 = 1.0 - t;
      scale2 = sign2 * t;
   }


   //-----------------------------------
   // actually do the interpolation:

   x = F32(scale1 * q1.x + scale2 * q2.x);
   y = F32(scale1 * q1.y + scale2 * q2.y);
   z = F32(scale1 * q1.z + scale2 * q2.z);
   w = F32(scale1 * q1.w + scale2 * q2.w);
   return *this;
}
Ejemplo n.º 6
0
void ScatterSky::_generateSkyPoints()
{
   U32 rings=60, segments=20;//rings=160, segments=20;

   Point3F tmpPoint( 0, 0, 0 );

   // Establish constants used in sphere generation.
   F32 deltaRingAngle = ( M_PI_F / (F32)(rings * 2) );
   F32 deltaSegAngle = ( 2.0f * M_PI_F / (F32)segments );

   // Generate the group of rings for the sphere.
   for( int ring = 0; ring < 2; ring++ )
   {
      F32 r0 = mSin( ring * deltaRingAngle );
      F32 y0 = mCos( ring * deltaRingAngle );

      // Generate the group of segments for the current ring.
      for( int seg = 0; seg < segments + 1 ; seg++ )
      {
         F32 x0 = r0 * sinf( seg * deltaSegAngle );
         F32 z0 = r0 * cosf( seg * deltaSegAngle );

         tmpPoint.set( x0, z0, y0 );
         tmpPoint.normalizeSafe();

         tmpPoint.x *= smEarthRadius + smAtmosphereRadius;
         tmpPoint.y *= smEarthRadius + smAtmosphereRadius;
         tmpPoint.z *= smEarthRadius + smAtmosphereRadius;
         tmpPoint.z -= smEarthRadius;

         if ( ring == 1 )
            mSkyPoints.push_back( tmpPoint );
      }
   }
}
Ejemplo n.º 7
0
GFXTextureObject* ShadowMapManager::getTapRotationTex()
{
    if ( mTapRotationTex.isValid() )
        return mTapRotationTex;

    mTapRotationTex.set( 64, 64, GFXFormatR8G8B8A8, &ShadowMapTexProfile,
                         "ShadowMapManager::getTapRotationTex" );

    GFXLockedRect *rect = mTapRotationTex.lock();
    U8 *f = rect->bits;
    F32 angle;
    for( U32 i = 0; i < 64*64; i++, f += 4 )
    {
        // We only pack the rotations into the red
        // and green channels... the rest are empty.
        angle = M_2PI_F * gRandGen.randF();
        f[0] = U8_MAX * ( ( 1.0f + mSin( angle ) ) * 0.5f );
        f[1] = U8_MAX * ( ( 1.0f + mCos( angle ) ) * 0.5f );
        f[2] = 0;
        f[3] = 0;
    }

    mTapRotationTex.unlock();

    return mTapRotationTex;
}
Ejemplo n.º 8
0
void EditTSCtrl::calcOrthoCamOffset(F32 mousex, F32 mousey, U8 modifier)
{
   F32 camScale = 0.01f;

   switch(mDisplayType)
   {
      case DisplayTypeTop:
         mOrthoCamTrans.x -= mousex * mOrthoFOV * camScale;
         mOrthoCamTrans.y += mousey * mOrthoFOV * camScale;
         break;

      case DisplayTypeBottom:
         mOrthoCamTrans.x -= mousex * mOrthoFOV * camScale;
         mOrthoCamTrans.y -= mousey * mOrthoFOV * camScale;
         break;

      case DisplayTypeFront:
         mOrthoCamTrans.x += mousex * mOrthoFOV * camScale;
         mOrthoCamTrans.z += mousey * mOrthoFOV * camScale;
         break;

      case DisplayTypeBack:
         mOrthoCamTrans.x -= mousex * mOrthoFOV * camScale;
         mOrthoCamTrans.z += mousey * mOrthoFOV * camScale;
         break;

      case DisplayTypeLeft:
         mOrthoCamTrans.y += mousex * mOrthoFOV * camScale;
         mOrthoCamTrans.z += mousey * mOrthoFOV * camScale;
         break;

      case DisplayTypeRight:
         mOrthoCamTrans.y -= mousex * mOrthoFOV * camScale;
         mOrthoCamTrans.z += mousey * mOrthoFOV * camScale;
         break;

      case DisplayTypeIsometric:
         if(modifier & SI_PRIMARY_CTRL)
         {
            // NOTE: Maybe move the center of rotation code to right mouse down to avoid compound errors?
            F32 rot = mDegToRad(mousex);

            Point3F campos = (mRawCamPos + mOrthoCamTrans) - mIsoCamRotCenter;
            MatrixF mat(EulerF(0, 0, rot));
            mat.mulP(campos);
            mOrthoCamTrans = (campos + mIsoCamRotCenter) - mRawCamPos;
            mIsoCamRot.z += rot;

         }
         else
         {
            mOrthoCamTrans.x -= mousex * mOrthoFOV * camScale * mCos(mIsoCamRot.z) - mousey * mOrthoFOV * camScale * mSin(mIsoCamRot.z);
            mOrthoCamTrans.y += mousex * mOrthoFOV * camScale * mSin(mIsoCamRot.z) + mousey * mOrthoFOV * camScale * mCos(mIsoCamRot.z);
         }
         break;
   }
}
Ejemplo n.º 9
0
//--------------------------------------------------------------------------
// Get wave offset for texture animations using a wave transform
//--------------------------------------------------------------------------
F32 ProcessedShaderMaterial::_getWaveOffset( U32 stage )
{
   switch( mMaterial->mWaveType[stage] )
   {
   case Material::Sin:
      {
         return mMaterial->mWaveAmp[stage] * mSin( M_2PI * mMaterial->mWavePos[stage] );
         break;
      }

   case Material::Triangle:
      {
         F32 frac = mMaterial->mWavePos[stage] - mFloor( mMaterial->mWavePos[stage] );
         if( frac > 0.0 && frac <= 0.25 )
         {
            return mMaterial->mWaveAmp[stage] * frac * 4.0;
         }

         if( frac > 0.25 && frac <= 0.5 )
         {
            return mMaterial->mWaveAmp[stage] * ( 1.0 - ((frac-0.25)*4.0) );
         }

         if( frac > 0.5 && frac <= 0.75 )
         {
            return mMaterial->mWaveAmp[stage] * (frac-0.5) * -4.0;
         }

         if( frac > 0.75 && frac <= 1.0 )
         {
            return -mMaterial->mWaveAmp[stage] * ( 1.0 - ((frac-0.75)*4.0) );
         }

         break;
      }

   case Material::Square:
      {
         F32 frac = mMaterial->mWavePos[stage] - mFloor( mMaterial->mWavePos[stage] );
         if( frac > 0.0 && frac <= 0.5 )
         {
            return 0.0;
         }
         else
         {
            return mMaterial->mWaveAmp[stage];
         }
         break;
      }

   }

   return 0.0;
}
void AdvancedLightBinManager::setupSGData( SceneData &data, const SceneRenderState* state, LightInfo *light )
{
   PROFILE_SCOPE( AdvancedLightBinManager_setupSGData );

   data.lights[0] = light;
   data.ambientLightColor = state->getAmbientLightColor();
   data.objTrans = &MatrixF::Identity;

   if ( light )
   {
      if ( light->getType() == LightInfo::Point )
      {
         // The point light volume gets some flat spots along
         // the perimiter mostly visible in the constant and 
         // quadradic falloff modes.
         //
         // To account for them slightly increase the scale 
         // instead of greatly increasing the polycount.

         mLightMat = light->getTransform();
         mLightMat.scale( light->getRange() * 1.01f );
         data.objTrans = &mLightMat;
      }
      else if ( light->getType() == LightInfo::Spot )
      {
         mLightMat = light->getTransform();

         // Rotate it to face down the -y axis.
         MatrixF scaleRotateTranslate( EulerF( M_PI_F / -2.0f, 0.0f, 0.0f ) );

         // Calculate the radius based on the range and angle.
         F32 range = light->getRange().x;
         F32 radius = range * mSin( mDegToRad( light->getOuterConeAngle() ) * 0.5f );

         // NOTE: This fudge makes the cone a little bigger
         // to remove the facet egde of the cone geometry.
         radius *= 1.1f;

         // Use the scale to distort the cone to
         // match our radius and range.
         scaleRotateTranslate.scale( Point3F( radius, radius, range ) );

         // Apply the transform and set the position.
         mLightMat *= scaleRotateTranslate;
         mLightMat.setPosition( light->getPosition() );

         data.objTrans = &mLightMat;
      }
   }
}
Ejemplo n.º 11
0
QuatF & QuatF::extrapolate( const QuatF & q1, const QuatF & q2, F32 t )
{
   // assert t >= 0 && t <= 1
   // q1 is value at time = 0
   // q2 is value at time = t
   // Computes quaternion at time = 1
   F64 flip,cos = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w;
   if (cos < 0.0)
   {
      cos = -cos;
      flip = -1.0;
   }
   else
      flip = 1.0;

   F64 s1,s2;
   if ((1.0 - cos) > 0.00001)
   {
      F64 om = mAcos(cos) / t;
      F64 sd = 1.0 / mSin(t * om);
      s1 = flip * mSin(om) * sd;
      s2 = mSin((1.0 - t) * om) * sd;
   }
   else
   {
      // If quats are very close, do linear interpolation
      s1 = flip / t;
      s2 = (1.0 - t) / t;
   }

   x = F32(s1 * q2.x - s2 * q1.x);
   y = F32(s1 * q2.y - s2 * q1.y);
   z = F32(s1 * q2.z - s2 * q1.z);
   w = F32(s1 * q2.w - s2 * q1.w);

   return *this;
}
Ejemplo n.º 12
0
bool OculusVRDevice::process()
{
   if(!mEnabled)
      return false;

   if(!getActive())
      return false;

   //Build the maximum axis angle to be passed into the sensor process()
   F32 maxAxisRadius = mSin(mDegToRad(smMaximumAxisAngle));

   // Process each sensor
   for(U32 i=0; i<mSensorDevices.size(); ++i)
   {
      mSensorDevices[i]->process(mDeviceType, smGenerateAngleAxisRotationEvents, smGenerateEulerRotationEvents, smGenerateRotationAsAxisEvents, maxAxisRadius);
   }

   return true;
}
Ejemplo n.º 13
0
void Item::registerLights(LightManager * lightManager, bool lightingScene)
{
   if(lightingScene)
      return;

   if(mDataBlock->lightOnlyStatic && !mStatic)
      return;

   F32 intensity;
   switch(mDataBlock->lightType)
   {
      case ConstantLight:
         intensity = mFadeVal;
         break;

      case PulsingLight:
      {
         S32 delta = Sim::getCurrentTime() - mDropTime;
         intensity = 0.5f + 0.5f * mSin(M_PI_F * F32(delta) / F32(mDataBlock->lightTime));
         intensity = 0.15f + intensity * 0.85f;
         intensity *= mFadeVal;  // fade out light on flags
         break;
      }

      default:
         return;
   }

   // Create a light if needed
   if (!mLight)
   {
      mLight = lightManager->createLightInfo();
   }   
   mLight->setColor( mDataBlock->lightColor * intensity );
   mLight->setType( LightInfo::Point );
   mLight->setRange( mDataBlock->lightRadius );
   mLight->setPosition( getBoxCenter() );

   lightManager->registerGlobalLight( mLight, this );
}
Ejemplo n.º 14
0
void ForestWindMgr::updateWind(  const Point3F &camPos, 
                                 const TreePlacementInfo &info, 
                                 F32 timeDelta )
{
   PROFILE_SCOPE(ForestWindMgr_updateWind);

   // See if we have the blended source available.
   ForestWindAccumulator *blendDest = NULL;
   {
      IdToWindMap::Iterator iter = mPrevSources->find( info.itemKey );
      if ( iter != mPrevSources->end() )
      {
         blendDest = iter->value;
         mPrevSources->erase( iter );
      }
   }

   // Get some stuff we'll need for finding the emitters.
   F32 treeHeight = info.scale * info.dataBlock->getObjBox().len_z();
   Point3F top = info.pos;
   top.z += treeHeight;
   if ( blendDest )
      top += ( 1.0f / info.scale ) * blendDest->getDirection();

   // Go thru the emitters to accumulate the total wind force.
   VectorF windForce( 0, 0, 0 );

   F32 time = Sim::getCurrentTime() / 1000.0f;

   ForestWindEmitterList::iterator iter = mEmitters.begin();
   for ( ; iter != mEmitters.end(); iter++ )
   {
      ForestWindEmitter *emitter = (*iter);

      // If disabled or no wind object... skip it.
      if ( !emitter->isEnabled() || !emitter->getWind() )
         continue;

      ForestWind *wind = emitter->getWind();

      F32 strength = wind->getStrength();
      
      if ( emitter->isRadialEmitter() )
      {
         Point3F closest = MathUtils::mClosestPointOnSegment( info.pos, top, emitter->getPosition() );
         Point3F dir = closest - emitter->getPosition();
         F32 lenSquared = dir.lenSquared();
         if ( lenSquared > emitter->getWindRadiusSquared() )
            continue;

         dir *= 1.0f / mSqrt( lenSquared );

         F32 att = lenSquared / emitter->getWindRadiusSquared();
         strength *= 1.0f - att;
         windForce += dir * strength;
      }
      else
      {
         F32 d = mDot( info.pos, Point3F::One ); //PlaneF( Point3F::Zero, wind->getDirection() ).distToPlane( Point3F( info.pos.x, info.pos.y, 0 ) );
         //F32 d = PlaneF( Point3F::Zero, wind->getDirection() ).distToPlane( Point3F( info.pos.x, info.pos.y, 0 ) );
         F32 scale = 1.0f + ( mSin( d + ( time / 10.0 ) ) * 0.5f );
         windForce += wind->getDirection() * strength * scale;
      }
   }

   // If we need a accumulator then we also need to presimulate.
   if ( !blendDest )
   {
      blendDest = new ForestWindAccumulator( info );
      blendDest->presimulate( windForce, 4.0f / TickSec );
   }
   else
      blendDest->updateWind( windForce, timeDelta );

   mSources->insertUnique( info.itemKey, blendDest );
}
bool LeapMotionDevice::process()
{
   if(!mEnabled)
      return false;

   if(!getActive())
      return false;

   //Con::printf("LeapMotionDevice::process()");

   //Build the maximum hand axis angle to be passed into the LeapMotionDeviceData::setData()
   F32 maxHandAxisRadius = mSin(mDegToRad(smMaximumHandAxisAngle));

   // Get a frame of data
   const Leap::Frame frame = mController->frame();

   //const Leap::HandList hands = frame.hands();
   //Con::printf("Frame: %lld  Hands: %d  Fingers: %d  Tools: %d", (long long)frame.id(), hands.count(), frame.fingers().count(), frame.tools().count());

   // Store the current data
   LeapMotionDeviceData* currentBuffer = (mPrevData == mDataBuffer[0]) ? mDataBuffer[1] : mDataBuffer[0];
   currentBuffer->setData(frame, mPrevData, smKeepHandIndexPersistent, smKeepPointableIndexPersistent, maxHandAxisRadius);
   U32 diff = mPrevData->compare(currentBuffer);
   U32 metaDiff = mPrevData->compareMeta(currentBuffer);

   // Update the previous data pointers.  We do this here in case someone calls our
   // console functions during one of the input events below.
   mPrevData = currentBuffer;

   // Send out any meta data
   if(metaDiff & LeapMotionDeviceData::METADIFF_FRAME_VALID_DATA)
   {
      // Frame valid change event
      INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_BUTTON, LM_FRAMEVALIDDATA, currentBuffer->mHasTrackingData ? SI_MAKE : SI_BREAK, currentBuffer->mHasTrackingData ? 1.0f : 0.0f);
   }

   // Send out any valid data
   if(currentBuffer->mDataSet && currentBuffer->mIsValid)
   {
      // Hands and their pointables
      if(smGenerateIndividualEvents)
      {
         for(U32 i=0; i<LeapMotionConstants::MaxHands; ++i)
         {
            if(currentBuffer->mHandValid[i])
            {
               // Send out position
               INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_POS, LM_HAND[i], SI_MOVE, currentBuffer->mHandPosPoint[i]);

               // Send out rotation
               INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_ROT, LM_HANDROT[i], SI_MOVE, currentBuffer->mHandRotQuat[i]);

               // Pointables for hand
               for(U32 j=0; j<LeapMotionConstants::MaxPointablesPerHand; ++j)
               {
                  if(currentBuffer->mPointableValid[i][j])
                  {
                     // Send out position
                     INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_POS, LM_HANDPOINTABLE[i][j], SI_MOVE, currentBuffer->mPointablePosPoint[i][j]);

                     // Send out rotation
                     INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_ROT, LM_HANDPOINTABLEROT[i][j], SI_MOVE, currentBuffer->mPointableRotQuat[i][j]);
                  }
               }
            }
         }
      }

      // Single Hand as axis rotation
      if(smGenerateSingleHandRotationAsAxisEvents && diff & LeapMotionDeviceData::DIFF_HANDROTAXIS)
      {
         if(diff & LeapMotionDeviceData::DIFF_HANDROTAXISX)
            INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_AXIS, LM_HANDAXISX, SI_MOVE, currentBuffer->mHandRotAxis[0]);
         if(diff & LeapMotionDeviceData::DIFF_HANDROTAXISY)
            INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_AXIS, LM_HANDAXISY, SI_MOVE, currentBuffer->mHandRotAxis[1]);
      }
   }

   // Send out whole frame event, but only if the special frame group is defined
   if(smGenerateWholeFrameEvents && LeapMotionFrameStore::isFrameGroupDefined())
   {
      S32 id = LEAPMOTIONFS->generateNewFrame(frame, maxHandAxisRadius);
      if(id != 0)
      {
         INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_INT, LM_FRAME, SI_VALUE, id);
      }
   }

   return true;
}
Ejemplo n.º 16
0
static void m_sincosD_C( F64 angle, F64 *s, F64 *c )
{
   *s = mSin( angle );
   *c = mCos( angle );
}
Ejemplo n.º 17
0
//--------------------------------------
static void m_sincos_C( F32 angle, F32 *s, F32 *c )
{
   *s = mSin( angle );
   *c = mCos( angle );
}
Ejemplo n.º 18
0
//-----------------------------------------------------------------------------
void CameraSpline::value(F32 t, CameraSpline::Knot *result, bool skip_rotation)
{
   // Do some easing in and out for t.
   if(!gBuilding)
   {
      F32 oldT = t;
      if(oldT < 0.5f)
      {
         t = 0.5f - (mSin( (0.5 - oldT) * M_PI ) / 2.f);
      }

      if((F32(size()) - 1.5f) > 0.f && oldT - (F32(size()) - 1.5f) > 0.f)
      {
         oldT -= (F32(size()) - 1.5f);
         t = (F32(size()) - 1.5f) + (mCos( (0.5f - oldT) * F32(M_PI) ) / 2.f);
      }
   }

   // Verify that t is in range [0 >= t > size]
//   AssertFatal(t >= 0.0f && t < (F32)size(), "t out of range");
   Knot *p1 = getKnot((S32)mFloor(t));
   Knot *p2 = next(p1);

   F32 i = t - mFloor(t);  // adjust t to 0 to 1 on p1-p2 interval

   if (p1->mPath == Knot::SPLINE)
   {
      Knot *p0 = (p1->mType == Knot::KINK) ? p1 : prev(p1);
      Knot *p3 = (p2->mType == Knot::KINK) ? p2 : next(p2);
      result->mPosition.x = mCatmullrom(i, p0->mPosition.x, p1->mPosition.x, p2->mPosition.x, p3->mPosition.x);
      result->mPosition.y = mCatmullrom(i, p0->mPosition.y, p1->mPosition.y, p2->mPosition.y, p3->mPosition.y);
      result->mPosition.z = mCatmullrom(i, p0->mPosition.z, p1->mPosition.z, p2->mPosition.z, p3->mPosition.z);
   }
   else
   {   // Linear
      result->mPosition.interpolate(p1->mPosition, p2->mPosition, i);
   }

   if (skip_rotation)
      return;

   buildTimeMap();

   // find the two knots to interpolate rotation and velocity through since some
   // knots are only positional
   S32 start = (S32)mFloor(t);
   S32 end   = (p2 == p1) ? start : (start + 1);
   while (p1->mType == Knot::POSITION_ONLY && p1 != front())
   {
      p1 = prev(p1);
      start--;
   }

   while (p2->mType == Knot::POSITION_ONLY && p2 != back())
   {
      p2 = next(p2);
      end++;
   }

   if (start == end) 
   {
      result->mRotation = p1->mRotation;
      result->mSpeed = p1->mSpeed;
   }
   else 
   {
      
      F32 c = getDistance(t);
      F32 d1 = getDistance((F32)start);
      F32 d2 = getDistance((F32)end);
      
      if (d1 == d2) 
      {
         result->mRotation = p2->mRotation;
         result->mSpeed    = p2->mSpeed;
      }
      else 
      {
         i  = (c-d1)/(d2-d1);

         if(p1->mPath == Knot::SPLINE)
         {
            Knot *p0 = (p1->mType == Knot::KINK) ? p1 : prev(p1);
            Knot *p3 = (p2->mType == Knot::KINK) ? p2 : next(p2);

            F32 q,w,e;
            q = mCatmullrom(i, 0, 1, 1, 1);
            w = mCatmullrom(i, 0, 0, 0, 1);
            e = mCatmullrom(i, 0, 0, 1, 1);

            QuatF a; a.interpolate(p0->mRotation, p1->mRotation, q);
            QuatF b; b.interpolate(p2->mRotation, p3->mRotation, w);
            
            result->mRotation.interpolate(a, b, e);
            result->mSpeed = mCatmullrom(i, p0->mSpeed, p1->mSpeed, p2->mSpeed, p3->mSpeed);
         }
         else
         {
            result->mRotation.interpolate(p1->mRotation, p2->mRotation, i);
            result->mSpeed = (p1->mSpeed * (1.0f-i)) + (p2->mSpeed * i);
         }
      }
   }
}
void afxZodiacTerrainRenderer::render(SceneRenderState* state)
{
   PROFILE_SCOPE(afxRenderZodiacTerrainMgr_render);

   // Early out if no terrain zodiacs to draw.
   if (terrain_zodes.size() == 0)
     return;

   initShader();
   if (!zodiac_shader)
     return;

   bool is_reflect_pass = state->isReflectPass();

   // Automagically save & restore our viewport and transforms.
   GFXTransformSaver saver;

   MatrixF proj = GFX->getProjectionMatrix();

   // Set up world transform
   MatrixF world = GFX->getWorldMatrix();
   proj.mul(world);
   shader_consts->set(projection_sc, proj);

   //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
   // RENDER EACH ZODIAC
   //
   for (S32 zz = 0; zz < terrain_zodes.size(); zz++)
   {
      TerrainZodiacElem& elem = terrain_zodes[zz];

      TerrainBlock* block = (TerrainBlock*) elem.block;

      afxZodiacMgr::ZodiacSpec* zode = &afxZodiacMgr::terr_zodes[elem.zode_idx];
      if (!zode)
         continue;

      if (is_reflect_pass)
      {
         if ((zode->zflags & afxZodiacData::SHOW_IN_REFLECTIONS) == 0)
            continue;
      }
      else
      {
         if ((zode->zflags & afxZodiacData::SHOW_IN_NON_REFLECTIONS) == 0)
            continue;
      }

      F32 fadebias = zode->calcDistanceFadeBias(elem.camDist);
      if (fadebias < 0.01f)
        continue;

      F32 cos_ang = mCos(elem.ang);
      F32 sin_ang = mSin(elem.ang);

      GFXStateBlock* sb = chooseStateBlock(zode->zflags & afxZodiacData::BLEND_MASK, is_reflect_pass);

      GFX->setShader(zodiac_shader->getShader());
      GFX->setStateBlock(sb);
      GFX->setShaderConstBuffer(shader_consts);

      // set the texture
      GFX->setTexture(0, *zode->txr);
      ColorF zode_color = (ColorF)zode->color;
      zode_color.alpha *= fadebias;
      shader_consts->set(color_sc, zode_color);

      Point3F half_size(zode->radius_xy,zode->radius_xy,zode->radius_xy);

      F32 inv_radius = 1.0f/zode->radius_xy;

      GFXPrimitive cell_prim;
      GFXVertexBufferHandle<TerrVertex> cell_verts;
      GFXPrimitiveBufferHandle  primBuff;
      elem.cell->getRenderPrimitive(&cell_prim, &cell_verts, &primBuff);

      U32 n_nonskirt_tris = TerrCellSpy::getMinCellSize()*TerrCellSpy::getMinCellSize()*2;

      const Point3F* verts = ((TerrCell*)elem.cell)->getZodiacVertexBuffer();
      const U16 *tris = block->getZodiacPrimitiveBuffer();
      if (!tris)
         continue; 

      PrimBuild::begin(GFXTriangleList, 3*n_nonskirt_tris);

      /////////////////////////////////
      U32 n_overlapping_tris = 0;
      U32 idx = 0;
      for (U32 i = 0; i < n_nonskirt_tris; i++)
      {
        Point3F tri_v[3];
        tri_v[0] = verts[tris[idx++]];
        tri_v[1] = verts[tris[idx++]];
        tri_v[2] = verts[tris[idx++]];

        elem.mRenderObjToWorld.mulP(tri_v[0]);
        elem.mRenderObjToWorld.mulP(tri_v[1]);
        elem.mRenderObjToWorld.mulP(tri_v[2]);

        if (!afxTriBoxOverlap2D(zode->pos, half_size, tri_v[0], tri_v[1], tri_v[2]))
          continue;

        n_overlapping_tris++;

        for (U32 j = 0; j < 3; j++)
        {
          // compute UV
          F32 u1 = (tri_v[j].x - zode->pos.x)*inv_radius;
          F32 v1 = (tri_v[j].y - zode->pos.y)*inv_radius;
          F32 ru1 = u1*cos_ang - v1*sin_ang;
          F32 rv1 = u1*sin_ang + v1*cos_ang;

          F32 uu = (ru1 + 1.0f)/2.0f;
          F32 vv = 1.0f - (rv1 + 1.0f)/2.0f;

          PrimBuild::texCoord2f(uu, vv);
          PrimBuild::vertex3fv(tri_v[j]);
        }
      }

      /////////////////////////////////

      PrimBuild::end(false);
   }
   //
   // RENDER EACH ZODIAC
   //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
}
Ejemplo n.º 20
0
void WaterObject::setShaderParams( SceneRenderState *state, BaseMatInstance *mat, const WaterMatParams &paramHandles )
{
   MaterialParameters* matParams = mat->getMaterialParameters();

   matParams->setSafe( paramHandles.mElapsedTimeSC, (F32)Sim::getCurrentTime() / 1000.0f );
   
   // set vertex shader constants
   //-----------------------------------   
   
   Point2F reflectTexSize( mPlaneReflector.reflectTex.getWidth(), mPlaneReflector.reflectTex.getHeight() );
   matParams->setSafe( paramHandles.mReflectTexSizeSC, reflectTexSize );

   static AlignedArray<Point2F> mConstArray( MAX_WAVES, sizeof( Point4F ) );   

   // Ripples...

   for ( U32 i = 0; i < MAX_WAVES; i++ )
      mConstArray[i].set( -mRippleDir[i].x, -mRippleDir[i].y );
   matParams->setSafe( paramHandles.mRippleDirSC, mConstArray );

   Point3F rippleSpeed( mRippleSpeed[0], mRippleSpeed[1], mRippleSpeed[2] );        
   matParams->setSafe( paramHandles.mRippleSpeedSC, rippleSpeed );

   Point4F rippleMagnitude( mRippleMagnitude[0], 
                            mRippleMagnitude[1], 
                            mRippleMagnitude[2],
                            mOverallRippleMagnitude );
   matParams->setSafe( paramHandles.mRippleMagnitudeSC, rippleMagnitude );

   for ( U32 i = 0; i < MAX_WAVES; i++ )
   {
      Point2F texScale = mRippleTexScale[i];
      if ( texScale.x > 0.0 )
         texScale.x = 1.0 / texScale.x;
      if ( texScale.y > 0.0 )
         texScale.y = 1.0 / texScale.y;

      mConstArray[i].set( texScale.x, texScale.y );
   }
   matParams->setSafe(paramHandles.mRippleTexScaleSC, mConstArray);

   static AlignedArray<Point4F> mConstArray4F( 3, sizeof( Point4F ) );

   F32 angle, cosine, sine;

   for ( U32 i = 0; i < MAX_WAVES; i++ )
   {
      angle = mAtan2( mRippleDir[i].x, -mRippleDir[i].y );
      cosine = mCos( angle );
      sine = mSin( angle );

      mConstArray4F[i].set( cosine, sine, -sine, cosine );
      matParams->setSafe( paramHandles.mRippleMatSC, mConstArray4F );
   }

   // Waves...

   for ( U32 i = 0; i < MAX_WAVES; i++ )
      mConstArray[i].set( -mWaveDir[i].x, -mWaveDir[i].y );
   matParams->setSafe( paramHandles.mWaveDirSC, mConstArray );

   for ( U32 i = 0; i < MAX_WAVES; i++ )
      mConstArray[i].set( mWaveSpeed[i], mWaveMagnitude[i] * mOverallWaveMagnitude );   
   matParams->setSafe( paramHandles.mWaveDataSC, mConstArray );   

   // Foam...

   Point4F foamDir( mFoamDir[0].x, mFoamDir[0].y, mFoamDir[1].x, mFoamDir[1].y );
   matParams->setSafe( paramHandles.mFoamDirSC, foamDir );

   Point2F foamSpeed( mFoamSpeed[0], mFoamSpeed[1] );        
   matParams->setSafe( paramHandles.mFoamSpeedSC, foamSpeed );

   //Point3F rippleMagnitude( mRippleMagnitude[0] * mOverallRippleMagnitude, 
   //                         mRippleMagnitude[1] * mOverallRippleMagnitude, 
   //                         mRippleMagnitude[2] * mOverallRippleMagnitude );
   //matParams->setSafe( paramHandles.mRippleMagnitudeSC, rippleMagnitude );

   Point4F foamTexScale( mFoamTexScale[0].x, mFoamTexScale[0].y, mFoamTexScale[1].x, mFoamTexScale[1].y );

   for ( U32 i = 0; i < 4; i++ )
   {
      if ( foamTexScale[i] > 0.0f )
         foamTexScale[i] = 1.0 / foamTexScale[i];      
   }

   matParams->setSafe(paramHandles.mFoamTexScaleSC, foamTexScale);

   // Other vert params...

   matParams->setSafe( paramHandles.mUndulateMaxDistSC, mUndulateMaxDist );

   // set pixel shader constants
   //-----------------------------------

   Point2F fogParams( mWaterFogData.density, mWaterFogData.densityOffset );
   matParams->setSafe(paramHandles.mFogParamsSC, fogParams );

   matParams->setSafe(paramHandles.mFarPlaneDistSC, (F32)state->getFarPlane() );

   Point2F wetnessParams( mWaterFogData.wetDepth, mWaterFogData.wetDarkening );
   matParams->setSafe(paramHandles.mWetnessParamsSC, wetnessParams );

   Point3F distortionParams( mDistortStartDist, mDistortEndDist, mDistortFullDepth );
   matParams->setSafe(paramHandles.mDistortionParamsSC, distortionParams );

   LightInfo *sun = LIGHTMGR->getSpecialLight(LightManager::slSunLightType);
   const ColorF &sunlight = state->getAmbientLightColor();
   Point3F ambientColor = mEmissive ? Point3F::One : sunlight;
   matParams->setSafe(paramHandles.mAmbientColorSC, ambientColor );
   matParams->setSafe(paramHandles.mLightDirSC, sun->getDirection() );

   Point4F foamParams( mOverallFoamOpacity, mFoamMaxDepth, mFoamAmbientLerp, mFoamRippleInfluence );
   matParams->setSafe(paramHandles.mFoamParamsSC, foamParams );   

   Point4F miscParams( mFresnelBias, mFresnelPower, mClarity, mMiscParamW );
   matParams->setSafe( paramHandles.mMiscParamsSC, miscParams );
   
   Point4F specularParams( mSpecularColor.red, mSpecularColor.green, mSpecularColor.blue, mSpecularPower );   
   if ( !mEmissive )
   {
      const ColorF &sunColor = sun->getColor();
      F32 brightness = sun->getBrightness();
      specularParams.x *= sunColor.red * brightness;
      specularParams.y *= sunColor.green * brightness;
      specularParams.z *= sunColor.blue * brightness;
   }
   matParams->setSafe( paramHandles.mSpecularParamsSC, specularParams );

   matParams->setSafe( paramHandles.mDepthGradMaxSC, mDepthGradientMax );

   matParams->setSafe( paramHandles.mReflectivitySC, mReflectivity );
}
void fxShapeReplicator::CreateShapes(void)
{
   F32				HypX, HypY;
   F32				Angle;
   U32				RelocationRetry;
   Point3F			ShapePosition;
   Point3F			ShapeStart;
   Point3F			ShapeEnd;
   Point3F			ShapeScale;
   EulerF			ShapeRotation;
   QuatF			QRotation;
   bool			CollisionResult;
   RayInfo			RayEvent;
   TSShape*		pShape;


   // Don't create shapes if we are hiding replications.
   if (mFieldData.mHideReplications) return;

   // Cannot continue without shapes!
   if (dStrcmp(mFieldData.mShapeFile, "") == 0) return;

   // Check that we can position somewhere!
   if (!(	mFieldData.mAllowOnTerrain ||
      mFieldData.mAllowStatics ||
      mFieldData.mAllowOnWater))
   {
      // Problem ...
      Con::warnf(ConsoleLogEntry::General, "[%s] - Could not place object, All alloweds are off!", getName());

      // Return here.
      return;
   }

   // Check Shapes.
   AssertFatal(mCurrentShapeCount==0,"Shapes already present, this should not be possible!")

      // Check that we have a shape...
      if (!mFieldData.mShapeFile) return;

   // Set Seed.
   RandomGen.setSeed(mFieldData.mSeed);

   // Set shape vector.
   mReplicatedShapes.clear();

   // Add shapes.
   for (U32 idx = 0; idx < mFieldData.mShapeCount; idx++)
   {
      fxShapeReplicatedStatic*	fxStatic;

      // Create our static shape.
      fxStatic = new fxShapeReplicatedStatic();

      // Set the 'shapeName' field.
      fxStatic->setField("shapeName", mFieldData.mShapeFile);

      // Is this Replicator on the Server?
      if (isServerObject())
         // Yes, so stop it from Ghosting. (Hack, Hack, Hack!)
         fxStatic->touchNetFlags(Ghostable, false);
      else
         // No, so flag as ghost object. (Another damn Hack!)
         fxStatic->touchNetFlags(IsGhost, true);

      // Register the Object.
      if (!fxStatic->registerObject())
      {
         // Problem ...
         Con::warnf(ConsoleLogEntry::General, "[%s] - Could not load shape file '%s'!", getName(), mFieldData.mShapeFile);

         // Destroy Shape.
         delete fxStatic;

         // Destroy existing hapes.
         DestroyShapes();

         // Quit.
         return;
      }

      // Get Allocated Shape.
      pShape = fxStatic->getShape();

      // Reset Relocation Retry.
      RelocationRetry = mFieldData.mShapeRetries;

      // Find it a home ...
      do
      {
         // Get the Replicator Position.
         ShapePosition = getPosition();

         // Calculate a random offset
         HypX	= RandomGen.randF(mFieldData.mInnerRadiusX, mFieldData.mOuterRadiusX);
         HypY	= RandomGen.randF(mFieldData.mInnerRadiusY, mFieldData.mOuterRadiusY);
         Angle	= RandomGen.randF(0, (F32)M_2PI);

         // Calcualte the new position.
         ShapePosition.x += HypX * mCos(Angle);
         ShapePosition.y += HypY * mSin(Angle);


         // Initialise RayCast Search Start/End Positions.
         ShapeStart = ShapeEnd = ShapePosition;
         ShapeStart.z = 2000.f;
         ShapeEnd.z= -2000.f;

         // Is this the Server?
         if (isServerObject())
            // Perform Ray Cast Collision on Server Terrain.
            CollisionResult = gServerContainer.castRay(ShapeStart, ShapeEnd, FXREPLICATOR_COLLISION_MASK, &RayEvent);
         else
            // Perform Ray Cast Collision on Client Terrain.
            CollisionResult = gClientContainer.castRay(	ShapeStart, ShapeEnd, FXREPLICATOR_COLLISION_MASK, &RayEvent);

         // Did we hit anything?
         if (CollisionResult)
         {
            // For now, let's pretend we didn't get a collision.
            CollisionResult = false;

            // Yes, so get it's type.
            U32 CollisionType = RayEvent.object->getTypeMask();

            // Check Illegal Placements.
            if (((CollisionType & TerrainObjectType) && !mFieldData.mAllowOnTerrain)	||
               ((CollisionType & StaticShapeObjectType) && !mFieldData.mAllowStatics)	||
               ((CollisionType & WaterObjectType) && !mFieldData.mAllowOnWater) ) continue;

            // If we collided with water and are not allowing on the water surface then let's find the
            // terrain underneath and pass this on as the original collision else fail.
            //
            // NOTE:- We need to do this on the server/client as appropriate.
            if ((CollisionType & WaterObjectType) && !mFieldData.mAllowWaterSurface)
            {
               // Is this the Server?
               if (isServerObject())
               {
                  // Yes, so do it on the server container.
                  if (!gServerContainer.castRay( ShapeStart, ShapeEnd, FXREPLICATOR_NOWATER_COLLISION_MASK, &RayEvent)) continue;
               }
               else
               {
                  // No, so do it on the client container.
                  if (!gClientContainer.castRay( ShapeStart, ShapeEnd, FXREPLICATOR_NOWATER_COLLISION_MASK, &RayEvent)) continue;
               }
            }

            // We passed with flying colours so carry on.
            CollisionResult = true;
         }

         // Invalidate if we are below Allowed Terrain Angle.
         if (RayEvent.normal.z < mSin(mDegToRad(90.0f-mFieldData.mAllowedTerrainSlope))) CollisionResult = false;

         // Wait until we get a collision.
      } while(!CollisionResult && --RelocationRetry);

      // Check for Relocation Problem.
      if (RelocationRetry > 0)
      {
         // Adjust Impact point.
         RayEvent.point.z += mFieldData.mOffsetZ;

         // Set New Position.
         ShapePosition = RayEvent.point;
      }
      else
      {
         // Warning.
         Con::warnf(ConsoleLogEntry::General, "[%s] - Could not find satisfactory position for shape '%s' on %s!", getName(), mFieldData.mShapeFile,isServerObject()?"Server":"Client");

         // Unregister Object.
         fxStatic->unregisterObject();

         // Destroy Shape.
         delete fxStatic;

         // Skip to next.
         continue;
      }

      // Get Shape Transform.
      MatrixF XForm = fxStatic->getTransform();

      // Are we aligning to Terrain?
      if (mFieldData.mAlignToTerrain)
      {
         // Yes, so set rotation to Terrain Impact Normal.
         ShapeRotation = RayEvent.normal * mFieldData.mTerrainAlignment;
      }
      else
      {
         // No, so choose a new Rotation (in Radians).
         ShapeRotation.set(	mDegToRad(RandomGen.randF(mFieldData.mShapeRotateMin.x, mFieldData.mShapeRotateMax.x)),
            mDegToRad(RandomGen.randF(mFieldData.mShapeRotateMin.y, mFieldData.mShapeRotateMax.y)),
            mDegToRad(RandomGen.randF(mFieldData.mShapeRotateMin.z, mFieldData.mShapeRotateMax.z)));
      }

      // Set Quaternion Roation.
      QRotation.set(ShapeRotation);

      // Set Transform Rotation.
      QRotation.setMatrix(&XForm);

      // Set Position.
      XForm.setColumn(3, ShapePosition);

      // Set Shape Position / Rotation.
      fxStatic->setTransform(XForm);

      // Choose a new Scale.
      ShapeScale.set(	RandomGen.randF(mFieldData.mShapeScaleMin.x, mFieldData.mShapeScaleMax.x),
         RandomGen.randF(mFieldData.mShapeScaleMin.y, mFieldData.mShapeScaleMax.y),
         RandomGen.randF(mFieldData.mShapeScaleMin.z, mFieldData.mShapeScaleMax.z));

      // Set Shape Scale.
      fxStatic->setScale(ShapeScale);

      // Lock it.
      fxStatic->setLocked(true);

      // Store Shape in Replicated Shapes Vector.
      //mReplicatedShapes[mCurrentShapeCount++] = fxStatic;
      mReplicatedShapes.push_back(fxStatic);

   }

   mCurrentShapeCount = mReplicatedShapes.size();

   // Take first Timestamp.
   mLastRenderTime = Platform::getVirtualMilliseconds();
}
Ejemplo n.º 22
0
F32 TimeOfDay::_calcAzimuth( F32 lat, F32 dec, F32 mer )
{
   // Add PI to normalize this from the range of -PI/2 to PI/2 to 0 to 2 * PI;
	  return mAtan2( mSin(mer), mCos(mer) * mSin(lat) - mTan(dec) * mCos(lat) ) + M_PI_F;
}
Ejemplo n.º 23
0
F32 TimeOfDay::_calcElevation( F32 lat, F32 dec, F32 mer )
{
   return mAsin( mSin(lat) * mSin(dec) + mCos(lat) * mCos(dec) * mCos(mer) );
}
Ejemplo n.º 24
0
bool EditTSCtrl::processCameraQuery(CameraQuery * query)
{
   if(mDisplayType == DisplayTypePerspective)
   {
      query->ortho = false;
   }
   else
   {
      query->ortho = true;
   }

   if (getCameraTransform(&query->cameraMatrix))
   {
      query->farPlane = gClientSceneGraph->getVisibleDistance() * smVisibleDistanceScale;
      query->nearPlane = gClientSceneGraph->getNearClip();
      query->fov = mDegToRad(smCamFOV);

      if(query->ortho)
      {
         MatrixF camRot(true);
         const F32 camBuffer = 1.0f;
         Point3F camPos = query->cameraMatrix.getPosition();

         F32 isocamplanedist = 0.0f;
         if(mDisplayType == DisplayTypeIsometric)
         {
            const RectI& vp = GFX->getViewport();
            isocamplanedist = 0.25 * vp.extent.y * mSin(mIsoCamAngle);
         }

         // Calculate the scene bounds
         Box3F sceneBounds;
         computeSceneBounds(sceneBounds);

         if(!sceneBounds.isValidBox())
         {
            sceneBounds.maxExtents = camPos + smMinSceneBounds;
            sceneBounds.minExtents = camPos - smMinSceneBounds;
         }
         else
         {
            query->farPlane = getMax(smMinSceneBounds.x * 2.0f, (sceneBounds.maxExtents - sceneBounds.minExtents).len() + camBuffer * 2.0f + isocamplanedist);
         }

         mRawCamPos = camPos;
         camPos += mOrthoCamTrans;

         switch(mDisplayType)
         {
            case DisplayTypeTop:
               camRot.setColumn(0, Point3F(1.0, 0.0,  0.0));
               camRot.setColumn(1, Point3F(0.0, 0.0, -1.0));
               camRot.setColumn(2, Point3F(0.0, 1.0,  0.0));
               camPos.z = getMax(camPos.z + smMinSceneBounds.z, sceneBounds.maxExtents.z + camBuffer);
               break;

            case DisplayTypeBottom:
               camRot.setColumn(0, Point3F(1.0,  0.0,  0.0));
               camRot.setColumn(1, Point3F(0.0,  0.0,  1.0));
               camRot.setColumn(2, Point3F(0.0, -1.0,  0.0));
               camPos.z = getMin(camPos.z - smMinSceneBounds.z, sceneBounds.minExtents.z - camBuffer);
               break;

            case DisplayTypeFront:
               camRot.setColumn(0, Point3F(-1.0,  0.0,  0.0));
               camRot.setColumn(1, Point3F( 0.0, -1.0,  0.0));
               camRot.setColumn(2, Point3F( 0.0,  0.0,  1.0));
               camPos.y = getMax(camPos.y + smMinSceneBounds.y, sceneBounds.maxExtents.y + camBuffer);
               break;

            case DisplayTypeBack:
               camRot.setColumn(0, Point3F(1.0,  0.0,  0.0));
               camRot.setColumn(1, Point3F(0.0,  1.0,  0.0));
               camRot.setColumn(2, Point3F(0.0,  0.0,  1.0));
               camPos.y = getMin(camPos.y - smMinSceneBounds.y, sceneBounds.minExtents.y - camBuffer);
               break;

            case DisplayTypeLeft:
               camRot.setColumn(0, Point3F( 0.0, -1.0,  0.0));
               camRot.setColumn(1, Point3F( 1.0,  0.0,  0.0));
               camRot.setColumn(2, Point3F( 0.0,  0.0,  1.0));
               camPos.x = getMin(camPos.x - smMinSceneBounds.x, sceneBounds.minExtents.x - camBuffer);
               break;

            case DisplayTypeRight:
               camRot.setColumn(0, Point3F( 0.0,  1.0,  0.0));
               camRot.setColumn(1, Point3F(-1.0,  0.0,  0.0));
               camRot.setColumn(2, Point3F( 0.0,  0.0,  1.0));
               camPos.x = getMax(camPos.x + smMinSceneBounds.x, sceneBounds.maxExtents.x + camBuffer);
               break;

            case DisplayTypeIsometric:
               camPos.z = sceneBounds.maxExtents.z + camBuffer + isocamplanedist;
               MatrixF angle(EulerF(mIsoCamAngle, 0, 0));
               MatrixF rot(mIsoCamRot);
               camRot.mul(rot, angle);
               break;
         }

         query->cameraMatrix = camRot;
         query->cameraMatrix.setPosition(camPos);
         query->fov = mOrthoFOV;
      }

      smCamMatrix = query->cameraMatrix;
      smCamMatrix.getColumn(3,&smCamPos);
      smCamOrtho = query->ortho;
      smCamNearPlane = query->nearPlane;

      return true;
   }
   return false;
}