Exemplo n.º 1
0
bool VolumetricFog::onAdd()
{
	if (!Parent::onAdd())
		return false;

	if (!VFRTM->IsInitialized())
	{
		Con::errorf("No VolumetricFogRTManager present!!");
		return false;
	}

	resetWorldBox();

	mShapeLoaded = LoadShape();

	setRenderTransform(mObjToWorld);

	addToScene();
	ColBox.set(getTransform(), (mObjBox.getExtents() * getScale() * COLBOX_SCALE));
	mObjSize = mWorldBox.getGreatestDiagonalLength();
	mObjScale = getScale();
	mTexTiles = mAbs(mTexTiles);
	mSpeed.set(mSpeed1.x, mSpeed1.y, mSpeed2.x, mSpeed2.y);
	mInvScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z));
	if (isClientObject())
	{
		InitTexture();
		return setupRenderer();
	}

	VFRTM->IncFogObjects();

	return true;
}
Exemplo n.º 2
0
String getUniqueName( const char *inName )
{
   String outName( inName );

   if ( outName.isEmpty() )
      return String::EmptyString;

   SimObject *dummy;

   if ( !Sim::findObject( outName, dummy ) )
      return outName;

   S32 suffixNumb = -1;
   String nameStr( String::GetTrailingNumber( outName, suffixNumb ) );
   suffixNumb = mAbs( suffixNumb ) + 1;

   #define MAX_TRIES 100

   for ( U32 i = 0; i < MAX_TRIES; i++ )
   {   
      outName = String::ToString( "%s%d", nameStr.c_str(), suffixNumb );

      if ( !Sim::findObject( outName, dummy ) )
         return outName;         

      suffixNumb++;
   }

   Con::errorf( "Sim::getUniqueName( %s ) - failed after %d attempts", inName, MAX_TRIES );
   return String::EmptyString;
}
Exemplo n.º 3
0
TEST(TimeManager, BasicAPI)
{
   handle handler;

   // Initialize the time manager...
   TimeManager time;
   time.timeEvent.notify(&handler, &handle::timeEvent);

   // Event loop till at least one second has passed.
   const U32 start = Platform::getRealMilliseconds();

   while(Process::processEvents())
   {
      // If we go too long, kill it off...
      if(Platform::getRealMilliseconds() - start > 30*1000)
      {
         EXPECT_TRUE(false)
            << "Terminated process loop due to watchdog, not due to time manager event, after 30 seconds.";
         Process::requestShutdown();
      }
   }
   const U32 end = Platform::getRealMilliseconds();

   // Now, confirm we have approximately similar elapsed times.
   S32 elapsedRealTime = end - start;
   EXPECT_LT(mAbs(elapsedRealTime - handler.mElapsedTime), 50)
      << "Failed to elapse time to within the desired tolerance.";
   EXPECT_GT(handler.mNumberCalls, 0)
      << "Somehow got no event callbacks from TimeManager?";
};
Exemplo n.º 4
0
bool VolumetricFog::onAdd()
{
    if (!Parent::onAdd())
        return false;

    if (!VFRTM->IsInitialized())
    {
        Con::errorf("No VolumetricFogRTManager present!!");
        return false;
    }

    resetWorldBox();

    mShapeLoaded = LoadShape();

    setRenderTransform(mObjToWorld);

    addToScene();
    ColBox.set(getTransform(), (mObjBox.getExtents() * getScale() * COLBOX_SCALE));
    mObjSize = mWorldBox.getGreatestDiagonalLength();
    mObjScale = getScale();
    mTexTiles = mAbs(mTexTiles);
    mSpeed.set(mSpeed1.x, mSpeed1.y, mSpeed2.x, mSpeed2.y);
    mInvScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z));

    if (isClientObject())
    {
        conn = GameConnection::getConnectionToServer();
        if (!conn)
        {
            Con::errorf("VolumetricFog::onAdd - No Serverconnection");
            return false;
        }

        glowFX = static_cast<PostEffect*>(Sim::findObject("VolFogGlowPostFx"));

        mOldLightRayStrength = Con::getFloatVariable("$LightRayPostFX::brightScalar",1.0f);

        GuiCanvas* cv = dynamic_cast<GuiCanvas*>(Sim::findObject("Canvas"));
        if (cv == NULL)
        {
            Con::errorf("VolumetricFog::onAdd - Canvas not found!!");
            return false;
        }
        mPlatformWindow = cv->getPlatformWindow();
        VolumetricFogRTManager::getVolumetricFogRTMResizeSignal().notify(this, &VolumetricFog::handleResize);
        GuiCanvas::getCanvasSizeChangeSignal().notify(this, &VolumetricFog::handleCanvasResize);

        InitTexture();
        return setupRenderer();
    }

    VFRTM->IncFogObjects();

    return true;
}
void GuiButtonBaseCtrl::onMouseDragged( const GuiEvent& event )
{
   if( mUseMouseEvents )
   {
      // If we haven't started a drag yet, find whether we have moved past
      // the tolerance value.
      
      if( !mMouseDragged )
      {
         Point2I delta = mMouseDownPoint - event.mousePoint;
         if( mAbs( delta.x ) > 2 || mAbs( delta.y ) > 2 )
            mMouseDragged = true;
      }
      
      if( mMouseDragged )
         onMouseDragged_callback();
   }
      
   Parent::onMouseDragged( event );
}
Exemplo n.º 6
0
//-----------------------------------------------------------------------------
//
// VFadeEvent::onTrigger( pTime, pDelta );
//
// Start the fade sequence if a valid fade control can be found.
//
//-----------------------------------------------------------------------------
void VFadeEvent::onTrigger( const S32 &pTime, const S32 &pDelta )
{
    Parent::onTrigger( pTime, pDelta );

    // Fetch GUI Control.
    VFadeControl *fadeControl;
    if ( !Sim::findObject( "VFadeControlGUI", fadeControl ) )
    {
        // Invalid.
        return;
    }

    // Start Fade.
    fadeControl->start( getFadeType(), mDuration );

    // Set Elapsed Time.
    fadeControl->mElapsedTime = mAbs( pTime - getStartTime() );
}
Exemplo n.º 7
0
//-----------------------------------------------------------------------------
// 
// VCameraShakeEvent::onTrigger( pTime, pDelta );
// 
// Start shaking the camera. Also account for any offet in playtime, and
// timescale.
// 
//-----------------------------------------------------------------------------
void VCameraShakeEvent::onTrigger( const S32 &pTime, const S32 &pDelta )
{
    Parent::onTrigger( pTime, pDelta );

    // Fetch Group.
    VCameraGroup *group;
    if ( !getGroup( group ) || !group->isActive() )
    {
        // Inactive.
        return;
    }

    // Duration.
    //const F32 duration  = ( mDuration - mAbs( pTime - getStartTime() ) ) / ( 1000.f * mFabs( getControllerTimeScale() ) );
    const F32 duration  = ( mDuration - mAbs( pTime - getStartTime() ) ) / 1000.f;

    // Shake Camera.
    VTorque::startCameraShake( duration, mFalloff, mAmplitude, mFrequency );
}
Exemplo n.º 8
0
void ClipMap::recenter(Point2F center)
{
   bool wantCompleteRefill = false;
   if(mNeedRefill || mForceClipmapPurge || Con::getBoolVariable("$forceFullClipmapPurgeEveryFrame", false))
      wantCompleteRefill = true;

   PROFILE_START(ClipMap_recenter);

   // Reset our budget.
   mMaxTexelUploadPerRecenter = mClipMapSize * mClipMapSize * 2;

   AssertFatal(isPow2(mClipMapSize), 
      "ClipMap::recenter - require pow2 clipmap size!");

   // Clamp the center to the unit square.

   /*
   if(!mTile)
   {
      center.x = mClampF(center.x, 0.f, 1.f);
      center.y = mClampF(center.y, 0.f, 1.f);
   }
   */

   // Ok, we're going to do toroidal updates on each entry of the clipstack
   // (except for the cap, which covers the whole texture), based on this
   // new center point.
   if( !wantCompleteRefill )
   {
      // Calculate the new texel at most detailed level.
      Point2F texelCenterF = center * F32(mClipMapSize) * mLevels[0].mScale;
      Point2I texelCenter((S32)mFloor(texelCenterF.y), (S32)mFloor(texelCenterF.x));
      
      // Update interest region.
      mImageCache->setInterestCenter(texelCenter);
   }

   // Note how many we were at so we can cut off at the right time.
   S32 lastTexelsUpdated = mTexelsUpdated;

   // For each texture...
   for(S32 i=mClipStackDepth-2; i>=0; i--)
   {
      ClipStackEntry &cse = mLevels[i];

      // Calculate new center point for this texture.
      Point2F texelCenterF = center * F32(mClipMapSize) * cse.mScale;

      const S32 texelMin = mClipMapSize/2;
      //const S32 texelMax = S32(F32(mClipMapSize) * cse.mScale) - texelMin;

      Point2I texelTopLeft;

      //if(mTile)
      //{
         texelTopLeft.x = S32(mFloor(texelCenterF.y)) - texelMin;
         texelTopLeft.y = S32(mFloor(texelCenterF.x)) - texelMin;
      //}
      //else
      //{
      //   texelTopLeft.x = mClamp(S32(mFloor(texelCenterF.y)), texelMin, texelMax) - texelMin;
      //   texelTopLeft.y = mClamp(S32(mFloor(texelCenterF.x)), texelMin, texelMax) - texelMin;
      //}

      // Also, prevent very small updates - the RT changes are costly.
      Point2I d = cse.mToroidalOffset - texelTopLeft;
      if(mAbs(d.x) <= 2 && mAbs(d.y) <= 2)
      {
         // Update the center; otherwise we get some weird conditions around
         // edges of the clipmap space.
         cse.mClipCenter = center;
         continue;
      }

      // This + current toroid offset tells us what regions have to be blasted.
      RectI oldData(cse.mToroidalOffset,  Point2I(mClipMapSize, mClipMapSize));
      RectI newData(texelTopLeft,         Point2I(mClipMapSize, mClipMapSize));

      // Update clipstack level.
      cse.mClipCenter      = center;
      cse.mToroidalOffset  = texelTopLeft;

      // If we're refilling, that's all we want; continue with next level.
      if( wantCompleteRefill )
         continue;

      // Make sure we have available data...
      if(!mImageCache->isDataAvailable(getMipLevel(cse.mScale), newData))
		  continue;

      // Alright, determine the set of data we actually need to upload.
      S32   rectCount = 0;
      RectI buffer[8];

      calculateModuloDeltaBounds(oldData, newData, buffer, &rectCount);
      AssertFatal(rectCount < 8, "ClipMap::recenter - got too many rects back!");

      /*if(rectCount)
         Con::printf("    issuing %d updates to clipmap level %d (offset=%dx%d)", 
                        rectCount, i, texelTopLeft.x, texelTopLeft.y); */

      if(rectCount)
      {
         if (!mImageCache->beginRectUpdates(cse))
         {
            mForceClipmapPurge = true;
            return;
         }
         //Con::errorf("layer %x, %d updates", &cse,  rectCount);

         // And GO!
         for(S32 j=0; j<rectCount; j++)
         {
            PROFILE_START(ClipMap_recenter_upload);

            AssertFatal(buffer[j].isValidRect(),"ClipMap::recenter - got invalid rect!");

            // Note the rect, so we can then wrap and let the image cache do its thing.
            RectI srcRegion = buffer[j];
            buffer[j].point.x = srcRegion.point.x % mClipMapSize;
            buffer[j].point.y = srcRegion.point.y % mClipMapSize;

            AssertFatal(newData.contains(srcRegion), 
               "ClipMap::recenter - got update buffer outside of expected new data bounds.");

            mTotalUpdates++;
            mTexelsUpdated += srcRegion.extent.x  * srcRegion.extent.y;

            //Con::printf("updating (%d %d %d %d)",
            //   buffer[j].point.x, buffer[j].point.y, buffer[j].extent.x, buffer[j].extent.y);

            mImageCache->doRectUpdate(getMipLevel(cse.mScale), cse, srcRegion, buffer[j]);

            PROFILE_END();
         }

         mImageCache->finishRectUpdates(cse);
      }

      // Check if we've overrun our budget.
      if((mTexelsUpdated - lastTexelsUpdated) > mMaxTexelUploadPerRecenter)
      {
         //Con::warnf("ClipMap::recenter - exceeded budget for this frame, deferring till next frame.");
         break;
      }

   }

   if( wantCompleteRefill )
   {
      fillWithTextureData();
      mNeedRefill = false;
   }

   PROFILE_END();
}
Exemplo n.º 9
0
void ClipMap::calculateModuloDeltaBounds(const RectI &oldData, const RectI &newData, 
                                              RectI *outRects, S32 *outRectCount)
{
   // Sanity checking.
   /*AssertFatal(oldData.point.x >= 0 && oldData.point.y >= 0 && oldData.isValidRect(),
      "ClipMap::calculateModuloDeltaBounds - negative oldData origin or bad rect!");

   AssertFatal(newData.point.x >= 0 && newData.point.y >= 0 && newData.isValidRect(),
      "ClipMap::calculateModuloDeltaBounds - negative newData origin or bad rect!");*/

   AssertFatal(newData.extent == oldData.extent, 
      "ClipMap::calculateModuloDeltaBounts - mismatching extents, can only work with matching extents!");

   // Easiest case - if they're the same then do nothing.
   if(oldData.point == newData.point)
   {
      *outRectCount = 0;
      return;
   }

   // Easy case - if there's no overlap then it's all new!
   if(!oldData.overlaps(newData))
   {
      // Clip out to return buffer, and we're done.
      clipAgainstGrid(mClipMapSize, newData, outRectCount, outRects);
      return;
   }

   // Calculate some useful values for both X and Y. Delta is used a lot
   // in determining bounds, and the boundary values are important for
   // determining where to start copying new data in.
   const S32 xDelta = newData.point.x - oldData.point.x;
   const S32 yDelta = newData.point.y - oldData.point.y;

   const S32 xBoundary = (oldData.point.x + oldData.extent.x) % mClipMapSize;
   const S32 yBoundary = (oldData.point.y + oldData.extent.y) % mClipMapSize;

   AssertFatal(xBoundary % mClipMapSize == oldData.point.x % mClipMapSize, 
      "ClipMap::calculateModuleDeltaBounds - we assume that left and "
      "right of the dataset are identical (ie, it's periodical on size of clipmap!) (x)");

   AssertFatal(yBoundary % mClipMapSize == oldData.point.y % mClipMapSize, 
      "ClipMap::calculateModuleDeltaBounds - we assume that left and "
      "right of the dataset are identical (ie, it's periodical on size of clipmap!) (y)");

   // Now, let's build up our rects. We have one rect if we are moving
   // on the X or Y axis, two if both. We dealt with the no-move case
   // previously.
   if(xDelta == 0)
   {
      // Moving on Y! So generate and store clipped results.
      RectI yRect;

      if(yDelta < 0)
      {
         // We need to generate the box from right of old to right of new.
         yRect.point = newData.point;
         yRect.extent.x = mClipMapSize;
         yRect.extent.y = -yDelta;
      }
      else
      {
         // We need to generate the box from left of old to left of new.
         yRect.point.x = newData.point.x; // Doesn't matter which rect we get this from.
         yRect.point.y = (oldData.point.y + oldData.extent.y);
         yRect.extent.x = mClipMapSize;
         yRect.extent.y = yDelta;
      }

      // Clip out to return buffer, and we're done.
      clipAgainstGrid(mClipMapSize, yRect, outRectCount, outRects);

      return;
   }
   else if(yDelta == 0)
   {
      // Moving on X! So generate and store clipped results.
      RectI xRect;

      if(xDelta < 0)
      {
         // We need to generate the box from right of old to right of new.
         xRect.point = newData.point;
         xRect.extent.x = -xDelta;
         xRect.extent.y = mClipMapSize;
      }
      else
      {
         // We need to generate the box from left of old to left of new.
         xRect.point.x = (oldData.point.x + oldData.extent.x);
         xRect.point.y = newData.point.y; // Doesn't matter which rect we get this from.
         xRect.extent.x = xDelta;
         xRect.extent.y = mClipMapSize;
      }

      // Clip out to return buffer, and we're done.
      clipAgainstGrid(mClipMapSize, xRect, outRectCount, outRects);

      return;
   }
   else
   {
      // Both! We have an L shape. So let's do the bulk of it in one rect,
      // and the remainder in the other. We'll choose X as the dominant axis.
      //
      // a-----b---------c   going from e to a.
      // |     |         |
      // |     |         |
      // d-----e---------f   So the dominant rect is abgh and the passive
      // |     |         |   rect is bcef. Obviously depending on delta we
      // |     |         |   have to switch things around a bit.
      // |     |         |          y+ ^
      // |     |         |             |  
      // g-----h---------i   x+->      |

      RectI xRect, yRect;

      if(xDelta < 0)
      {
         // Case in the diagram.
         xRect.point = newData.point;
         xRect.extent.x = -xDelta;
         xRect.extent.y = mClipMapSize;

         // Set up what of yRect we know, too.
         yRect.point.x = xRect.point.x + xRect.extent.x;
         yRect.extent.x = mClipMapSize - mAbs(xDelta); 
      }
      else
      {
         // Opposite of case in diagram!
         xRect.point.x = oldData.point.x + oldData.extent.x;
         xRect.point.y = newData.point.y;
         xRect.extent.x = xDelta;
         xRect.extent.y = mClipMapSize;

         // Set up what of yRect we know,  too.
         yRect.point.x = (xRect.point.x + xRect.extent.x )- mClipMapSize;
         yRect.extent.x = mClipMapSize - xRect.extent.x;
      }

      if(yDelta < 0)
      {
         // Case in the diagram.
         yRect.point.y = newData.point.y;
         yRect.extent.y = -yDelta;
      }
      else
      {
         // Opposite of case in diagram!
         yRect.point.y = oldData.point.y + oldData.extent.y;
         yRect.extent.y = yDelta;
      }

      // Make sure we don't overlap.
      AssertFatal(!yRect.overlaps(xRect), 
         "ClipMap::calculateModuloDeltaBounds - have overlap in result rects!");

      // Ok, now run them through the clipper.
      S32 firstCount;
      clipAgainstGrid(mClipMapSize, xRect, &firstCount, outRects);
      clipAgainstGrid(mClipMapSize, yRect, outRectCount, outRects + firstCount);
      *outRectCount += firstCount;

      // All done!
      return;
   }
}
Exemplo n.º 10
0
//-----------------------------------------------------------------------------
//
// VMotionTrack::getObjectSpeed();
// 
// Determine the Speed that an object must move at to travel over the segment
// length of the Path.
//
//-----------------------------------------------------------------------------
F32 VMotionEvent::getObjectSpeed( void )
{
    // Fetch Parent Track.
    VMotionTrack *track;
    if ( !getTrack( track ) )
    {
        // Invalid Track.
        return 0.f;
    }

    // Fetch Path & Reference Object.
    VTorque::PathObjectType  *path   = track->getPath();
    VTorque::SceneObjectType *object = getSceneObject();
    if ( !path || !object )
    {
        // Invalid Object(s).
        return 0.f;
    }

    // Fetch Node Index.
    const S32 &srcNodeIndex = getNodeIndex( ( isControllerPlayingForward() ) ? 0 : -1 );

    // Fetch the Next Event.
    VEvent *nextEvent = getNextEvent();

    // Valid Destination Node?
    if ( !isControllerLooping() && !nextEvent )
    {
        // No Next Node.
        return 0.f;
    }

    // Valid Next Node?
    if ( nextEvent )
    {
        // Fetch Segment Length & Duration.
        const F32 &length   = VTorque::getPathNodeLength( path, srcNodeIndex );
        const F32 &duration = mAbs( getTriggerTime() - nextEvent->getTriggerTime() );

        // Speed = Distance / Duration.
        return ( length / ( duration / 1000.f ) );
    }

    // Playing Forwards?
    if ( isControllerPlayingForward() )
    {
        // Fetch the First Event.
        VEvent *firstEvent = dynamic_cast<VEvent*>( track->getChild() );

        // Fetch Segment Length & Duration.
        const F32 &length   = VTorque::getPathNodeLength( path, srcNodeIndex );
        const F32 &duration = ( getControllerDuration() - getTriggerTime() ) + firstEvent->getTriggerTime();

        // Speed = Distance / Duration.
        return ( length / ( duration / 1000.f ) );
    }

    // Fetch the Last Event.
    VEvent *lastEvent = dynamic_cast<VEvent*>( track->getLastChild() );

    // Fetch Segment Length & Duration.
    const F32 &length   = VTorque::getPathNodeLength( path, srcNodeIndex );
    const F32 &duration = ( getControllerDuration() - lastEvent->getTriggerTime() ) + getTriggerTime();

    // Speed = Distance / Duration.
    return ( length / ( duration / 1000.f ) );
}