GFXTextureObject* ReflectionManager::getRefractTex( bool forceUpdate )
{
   GFXTarget *target = GFX->getActiveRenderTarget();
   GFXFormat targetFormat = target->getFormat();
   const Point2I &targetSize = target->getSize();

#if defined(TORQUE_OS_XENON)
   // On the Xbox360, it needs to do a resolveTo from the active target, so this
   // may as well be the full size of the active target
   const U32 desWidth = targetSize.x;
   const U32 desHeight = targetSize.y;
#else
   const U32 desWidth = mFloor( (F32)targetSize.x * smRefractTexScale );
   const U32 desHeight = mFloor( ( F32)targetSize.y * smRefractTexScale );
#endif

   if ( mRefractTex.isNull() || 
        mRefractTex->getWidth() != desWidth ||
        mRefractTex->getHeight() != desHeight ||
        mRefractTex->getFormat() != targetFormat )
   {
      mRefractTex.set( desWidth, desHeight, targetFormat, &RefractTextureProfile, "mRefractTex" );    
      mUpdateRefract = true;
   }

   if ( forceUpdate || mUpdateRefract )
   {
      target->resolveTo( mRefractTex );   
      mUpdateRefract = false;
   }

   return mRefractTex;
}
// This "rounds" the projection matrix to remove subtexel movement during shadow map
// rasterization.  This is here to reduce shadow shimmering.
void PSSMLightShadowMap::_roundProjection(const MatrixF& lightMat, const MatrixF& cropMatrix, Point3F &offset, U32 splitNum)
{
   // Round to the nearest shadowmap texel, this helps reduce shimmering
   MatrixF currentProj = GFX->getProjectionMatrix();
   currentProj = cropMatrix * currentProj * lightMat;

   // Project origin to screen.
   Point4F originShadow4F(0,0,0,1);
   currentProj.mul(originShadow4F);
   Point2F originShadow(originShadow4F.x / originShadow4F.w, originShadow4F.y / originShadow4F.w);   

   // Convert to texture space (0..shadowMapSize)
   F32 t = mNumSplits < 4 ? mShadowMapTex->getWidth() / mNumSplits : mShadowMapTex->getWidth() / 2;
   Point2F texelsToTexture(t / 2.0f, mShadowMapTex->getHeight() / 2.0f);
   if (mNumSplits >= 4) texelsToTexture.y *= 0.5f;
   originShadow.convolve(texelsToTexture);

   // Clamp to texel boundary
   Point2F originRounded;
   originRounded.x = mFloor(originShadow.x + 0.5f);
   originRounded.y = mFloor(originShadow.y + 0.5f);

   // Subtract origin to get an offset to recenter everything on texel boundaries
   originRounded -= originShadow;

   // Convert back to texels (0..1) and offset
   originRounded.convolveInverse(texelsToTexture);
   offset.x += originRounded.x;
   offset.y += originRounded.y;
}
GFXTextureObject* ReflectionManager::getRefractTex()
{
   GFXTarget *target = GFX->getActiveRenderTarget();
   GFXFormat targetFormat = target->getFormat();
   const Point2I &targetSize = target->getSize();
   const U32 desWidth = mFloor( (F32)targetSize.x * mRefractTexScale );
   const U32 desHeight = mFloor( ( F32)targetSize.y * mRefractTexScale );

   if ( mRefractTex.isNull() || 
        mRefractTex->getWidth() != desWidth ||
        mRefractTex->getHeight() != desHeight ||
        mRefractTex->getFormat() != targetFormat )
   {
      mRefractTex.set( desWidth, desHeight, targetFormat, &RefractTextureProfile, "mRefractTex" );    
      mUpdateRefract = true;
   }

   if ( mUpdateRefract )
   {
      target->resolveTo( mRefractTex );   
      mUpdateRefract = false;
   }

   return mRefractTex;
}
bool VolumetricFogRTManager::Init()
{
   if (mIsInitialized)
   {
      Con::errorf("VolumetricFogRTManager allready initialized!!");
      return true;
   }
   
   GuiCanvas* cv = dynamic_cast<GuiCanvas*>(Sim::findObject("Canvas"));
   if (cv == NULL)
   {
      Con::errorf("VolumetricFogRTManager::Init() - Canvas not found!!");
      return false;
   }
   
   mPlatformWindow = cv->getPlatformWindow();
   mPlatformWindow->getScreenResChangeSignal().notify(this,&VolumetricFogRTManager::ResizeRT);
   
   if (mTargetScale < 1 || GFX->getAdapterType() == Direct3D11)
      mTargetScale = 1;
   
   mWidth = mFloor(mPlatformWindow->getClientExtent().x / mTargetScale);
   mHeight = mFloor(mPlatformWindow->getClientExtent().y / mTargetScale);
   
   mDepthBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F,
   &GFXRenderTargetProfile, avar("%s() - mDepthBuffer (line %d)", __FUNCTION__, __LINE__));
   if (!mDepthBuffer.isValid())
   {
      Con::errorf("VolumetricFogRTManager Fatal Error: Unable to create Depthbuffer");
      return false;
   }
   if (!mDepthTarget.registerWithName("volfogdepth"))
   {
      Con::errorf("VolumetricFogRTManager Fatal Error : Unable to register Depthbuffer");
      return false;
   }
   mDepthTarget.setTexture(mDepthBuffer);
   
   mFrontBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F,
   &GFXRenderTargetProfile, avar("%s() - mFrontBuffer (line %d)", __FUNCTION__, __LINE__));
   if (!mFrontBuffer.isValid())
   {
      Con::errorf("VolumetricFogRTManager Fatal Error: Unable to create front buffer");
      return false;
   }
   if (!mFrontTarget.registerWithName("volfogfront"))
   {
      Con::errorf("VolumetricFogRTManager Fatal Error : Unable to register Frontbuffer");
      return false;
   }
   
   mFrontTarget.setTexture(mFrontBuffer);
   
   Con::setVariable("$VolumetricFog::density", "0.0");
   
   mIsInitialized = true;
   
   return true;
}
Beispiel #5
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;
}
bool RenderTexTargetBinManager::_onPreRender(SceneRenderState * state, bool preserve /* = false */)
{
   PROFILE_SCOPE(RenderTexTargetBinManager_onPreRender);

#ifndef TORQUE_SHIPPING
   AssertFatal( m_NeedsOnPostRender == false, "_onPostRender not called on RenderTexTargetBinManager, or sub-class." );
   m_NeedsOnPostRender = false;
#endif

   // Update the render target size
   const Point2I &rtSize = GFX->getActiveRenderTarget()->getSize();
   switch(mTargetSizeType)
   {
   case WindowSize:
      setTargetSize(rtSize);
      break;
   case WindowSizeScaled:
      {
         Point2I scaledTargetSize(mFloor(rtSize.x * mTargetScale.x), mFloor(rtSize.y * mTargetScale.y));
         setTargetSize(scaledTargetSize);
         break;
      }
   case FixedSize:
      // No adjustment necessary
      break;
   }

   if( mTargetChainLength == 0 )
      return false;

   GFXTextureTargetRef binTarget = _getTextureTarget(mTargetChainIdx);

   if( binTarget.isNull() )
      return false;

   // Attach active depth target texture
   binTarget->attachTexture(GFXTextureTarget::DepthStencil, getRenderPass()->getDepthTargetTexture());

   // Preserve contents
   if(preserve)
      GFX->getActiveRenderTarget()->preserve();

   GFX->pushActiveRenderTarget();
   GFX->setActiveRenderTarget(binTarget);
   GFX->setViewport( mNamedTarget.getViewport() );

   #ifndef TORQUE_SHIPPING
      m_NeedsOnPostRender = true;
   #endif

   return true;
}
Beispiel #7
0
void CameraSpline::buildTimeMap()
{
   if (!mIsMapDirty)
      return;

   gBuilding = true;

   mTimeMap.clear();
   mTimeMap.reserve(size()*3);      // preallocate

   // Initial node and knot value..
   TimeMap map;
   map.mTime = 0;
   map.mDistance = 0;
   mTimeMap.push_back(map);

   Knot ka,kj,ki;
   value(0, &kj, true);
   F32 length = 0.0f;
   ka = kj;

   // Loop through the knots and add nodes. Nodes are added for every knot and
   // whenever the spline length and segment length deviate by epsilon.
   F32 epsilon = Con::getFloatVariable("CameraSpline::epsilon", 0.90f);
   const F32 Step = 0.05f;
   F32 lt = 0,time = 0;
   do  
   {
      if ((time += Step) > F32(mSize - 1))
         time = (F32)mSize - 1.0f;

      value(time, &ki, true);
      length += (ki.mPosition - kj.mPosition).len();
      F32 segment = (ki.mPosition - ka.mPosition).len();

      if ((segment / length) < epsilon || time == (mSize - 1) || mFloor(lt) != mFloor(time)) 
      {
         map.mTime = time;
         map.mDistance = length;
         mTimeMap.push_back(map);
         ka = ki;
      }
      kj = ki;
      lt = time;
   }
   while (time < mSize - 1);

   mIsMapDirty = false;

   gBuilding = false;
}
Beispiel #8
0
 bool default_scan(const String &data, Point2I & result)
 {
    // Handle passed as floating point from script
    if(data.find('.') != String::NPos)
    {
       Point2F tempResult;
       dSscanf(data.c_str(),"%f %f",&tempResult.x,&tempResult.y);
       result.x = mFloor(tempResult.x);
       result.y = mFloor(tempResult.y);
    }
    else
       dSscanf(data.c_str(),"%d %d",&result.x,&result.y);
    return true;
 }
Box3F PSSMLightShadowMap::_calcClipSpaceAABB(const Frustum& f, const MatrixF& transform, F32 farDist)
{
   // Calculate frustum center
   Point3F center(0,0,0);
   for (U32 i = 0; i < 8; i++)   
   {
      const Point3F& pt = f.getPoints()[i];      
      center += pt;
   }
   center /= 8;

   // Calculate frustum bounding sphere radius
   F32 radius = 0.0f;
   for (U32 i = 0; i < 8; i++)      
      radius = getMax(radius, (f.getPoints()[i] - center).lenSquared());
   radius = mFloor( mSqrt(radius) );
      
   // Now build box for sphere
   Box3F result;
   Point3F radiusBox(radius, radius, radius);
   result.minExtents = center - radiusBox;
   result.maxExtents = center + radiusBox;

   // Transform to light projection space
   transform.mul(result);
   
   return result;   
}
Beispiel #10
0
void SFXDSVoice::setPitch( F32 pitch )
{ 
   F32 sampleRate = _getBuffer()->getFormat().getSamplesPerSecond();
   F32 frequency = mFloor( mClampF( sampleRate * pitch, DSBFREQUENCY_MIN, DSBFREQUENCY_MAX ) );

   DSAssert( mDSBuffer->SetFrequency( ( U32 )frequency ), 
      "SFXDSVoice::setPitch - couldn't set playback frequency.");
}
//--------------------------------------------------------------------------
/// Function to draw a set of boxes blending throughout an array of colors
void GuiColorPickerCtrl::drawBlendRangeBox(RectI &bounds, bool vertical, U8 numColors, ColorI *colors)
{

   GFX->setStateBlock(mStateBlock);
   
   S32 l = bounds.point.x, r = bounds.point.x + bounds.extent.x + 4;
   S32 t = bounds.point.y, b = bounds.point.y + bounds.extent.y + 4;
   
   // Calculate increment value
   S32 x_inc = int(mFloor((r - l) / F32(numColors-1)));
   S32 y_inc = int(mFloor((b - t) / F32(numColors-1)));

   for( U16 i = 0;i < numColors - 1; i++ ) 
   {
      // This is not efficent, but then again it doesn't really need to be. -pw
      PrimBuild::begin( GFXTriangleFan, 4 );

      if (!vertical)  // Horizontal (+x)
      {
         // First color
         PrimBuild::color( colors[i] );
         PrimBuild::vertex2i( l, t );
         PrimBuild::vertex2i( l, b );

         // Second color
         PrimBuild::color( colors[i+1] );
         PrimBuild::vertex2i( l + x_inc, b );
         PrimBuild::vertex2i( l + x_inc, t );
         l += x_inc;
      }
      else  // Vertical (+y)
      {
         // First color
         PrimBuild::color( colors[i] );
         PrimBuild::vertex2i( l, t );
         PrimBuild::vertex2i( r, t );

         // Second color
         PrimBuild::color( colors[i+1] );
         PrimBuild::vertex2i( r, t + y_inc );
         PrimBuild::vertex2i( l, t + y_inc );
         t += y_inc;
      }
      PrimBuild::end();
   }
}
Beispiel #12
0
static S32 QSORT_CALLBACK compareReflectors( const void *a, const void *b )
{
   const ReflectorBase *A = *((ReflectorBase**)a);
   const ReflectorBase *B = *((ReflectorBase**)b);     
   
   F32 dif = B->score - A->score;
   return (S32)mFloor( dif );
}
Beispiel #13
0
void AtlasOldMesher::writeVertex(Stream *s, Vert *vert, const S8 level)
{
   S16 x, y, z;

   const Point2I &vertPos = vert->pos;
   Point3F center;
   mBounds.getCenter(&center);

   if (vert->special)
      z = vert->z;
   else
      z = mHeight->sampleRead(vertPos);

   S32 xTmp, yTmp;
   xTmp = (S32)mFloor(((vertPos.x * mHeight->mSampleSpacing - center.x) * mCompressionFactor.x) + 0.5);
   yTmp = (S32)mFloor(((vertPos.y * mHeight->mSampleSpacing - center.y) * mCompressionFactor.y) + 0.5);

   AssertFatal(S16(xTmp) == xTmp,
      "AtlasOldMesher::writeVertex - Overflow writing x-coordinate!");
   AssertFatal(S16(yTmp) == yTmp,
      "AtlasOldMesher::writeVertex - Overflow writing y-coordinate!");

   x = xTmp;
   y = yTmp;

   s->write(x);
   s->write(y);
   s->write(z);

   // Morph info.  Calculate the difference between the
   // vert height, and the height of the same spot in the
   // next lower-LOD mesh.
   S16 morphHeight;
   if (vert->special)
      morphHeight = z;	// special verts don't morph.
   else
   {
      morphHeight = mHeight->getHeightAtLOD(vertPos, level + 1);
   }

   S32 morphDelta = (S32(morphHeight) - S32(z));
   s->write(S16(morphDelta));

   if(morphDelta != S16(morphDelta))
      Con::warnf("AtlasOldMesher::writeVertex - overflow in lerpedHeight!");
}
S32 VideoCapture::getMsPerFrame()
{
   //Add accumulated error to ms per frame before rounding
   F32 roundTime = mFloor(mMsPerFrame + mMsPerFrameError + 0.5f);

   //Accumulate the rounding errors
   mMsPerFrameError += mMsPerFrame - roundTime;
      
   return (S32)roundTime;
}
bool VolumetricFogRTManager::Resize()
{
   if (mTargetScale < 1 || GFX->getAdapterType() == Direct3D11)
      mTargetScale = 1;

   mWidth = mFloor(mPlatformWindow->getClientExtent().x / mTargetScale);
   mHeight = mFloor(mPlatformWindow->getClientExtent().y / mTargetScale);
   
   if (mWidth < 16 || mHeight < 16)
      return false;
   
   if (mFrontTarget.isRegistered())
      mFrontTarget.setTexture(NULL);
   
   if (mDepthTarget.isRegistered())
      mDepthTarget.setTexture(NULL);
   
   if (mDepthBuffer.isValid())
      mDepthBuffer->kill();
   
   if (mFrontBuffer.isValid())
      mFrontBuffer->kill();
   
   mFrontBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F,
   &GFXRenderTargetProfile, avar("%s() - mFrontBuffer (line %d)", __FUNCTION__, __LINE__));
   if (!mFrontBuffer.isValid())
   {
      Con::errorf("VolumetricFogRTManager::Resize() Fatal Error: Unable to create front buffer");
      return false;
   }
   mFrontTarget.setTexture(mFrontBuffer);
   
   mDepthBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F,
   &GFXRenderTargetProfile, avar("%s() - mDepthBuffer (line %d)", __FUNCTION__, __LINE__));
   if (!mDepthBuffer.isValid())
   {
      Con::errorf("VolumetricFogRTManager::Resize() Fatal Error: Unable to create Depthbuffer");
      return false;
   }
   mDepthTarget.setTexture(mDepthBuffer);
   return true;
}
Beispiel #16
0
void SFXController::_onParameterEvent( SFXParameter* parameter, SFXParameterEvent event )
{
   Parent::_onParameterEvent( parameter, event );
   
   // Implement cursor semantic.
   
   if(    event == SFXParameterEvent_ValueChanged
       && parameter->getChannel() == SFXChannelCursor )
   {
      U32 slot = U32( mFloor( parameter->getValue() ) );
      if( slot != getCurrentSlot() )
         setCurrentSlot( slot );
   }
}
Beispiel #17
0
void GuiRolloutCtrl::animateTo( S32 height )
{
   // We do nothing if we're already animating
   if( mIsAnimating )
      return;

   bool collapsing = (bool)( getHeight() > height );

   // If we're already at the destination height, bail
   if ( getHeight() >= height && !collapsing )
   {
      mIsExpanded = true;
      return;
   }

   // If we're already at the destination height, bail
   if ( getHeight() <= height && collapsing )
   {
      mIsExpanded = false;
      return;
   }

   // Set destination height
   mAnimateDestHeight = height;

   // Set Animation Mode
   mCollapsing = collapsing;

   // Set Animation Step (Increment)
   if ( collapsing )
      mAnimateStep = (S32)mFloor( (F32)( getHeight() - height ) / 3.f );
   else
      mAnimateStep = (S32)mFloor( (F32)( height - getHeight() ) / 3.f );

   // Start our animation
   mIsAnimating = true;
}
void LeapMotionFrame::copyFromFrameHands(const Leap::HandList& hands, const F32& maxHandAxisRadius)
{
   // Set up Vectors
   mHandValid.increment(mHandCount);
   mHandId.increment(mHandCount);
   mHandRawPos.increment(mHandCount);
   mHandPos.increment(mHandCount);
   mHandRot.increment(mHandCount);
   mHandRotQuat.increment(mHandCount);
   mHandRotAxis.increment(mHandCount);
   mHandPointablesCount.increment(mHandCount);

   // Copy data
   for(U32 i=0; i<mHandCount; ++i)
   {
      const Leap::Hand& hand = hands[i];

      mHandValid[i] = hand.isValid();
      mHandId[i] = hand.id();
      
      // Position
      LeapMotionUtil::convertPosition(hand.palmPosition(), mHandRawPos[i]);
      mHandPos[i].x = (S32)mFloor(mHandRawPos[i].x);
      mHandPos[i].y = (S32)mFloor(mHandRawPos[i].y);
      mHandPos[i].z = (S32)mFloor(mHandRawPos[i].z);

      // Rotation
      LeapMotionUtil::convertHandRotation(hand, mHandRot[i]);
      mHandRotQuat[i].set(mHandRot[i]);

      // Thumb stick axis rotation
      LeapMotionUtil::calculateHandAxisRotation(mHandRot[i], maxHandAxisRadius, mHandRotAxis[i]);

      // Pointables
      mHandPointablesCount[i] = hand.pointables().count();
   }
}
Beispiel #19
0
void main()
{
	Floor mFloor(7);
	Container1 mContainer1(5, 1);
	Container2 mContainer2(5, 7);
	Control mControl(mFloor, 7);

	system("color F8");
	system("chcp 437");
	system("cls");

	InitialDisplay();

	int i;
	for(i = 1; i <= 7; i++)
		mFloor.Display(i);

	char key, firstInput = 0;
	while(1)
	{
		if(kbhit())
		{
			key = getch();
			if( KeyTest(key) )
			{
				if( firstInput == 0)
				{
					firstInput = key;
					DisplayKey(key, 0);
				}
				else
				{
					mFloor.PushPerson(firstInput - '0', key - '0');
					DisplayKey(firstInput, key);
					firstInput = 0;
				}
			}
		}

		mContainer1.Operater();
		mContainer2.Operater();
		mControl.Operator( mContainer1 );
		mControl.Operator( mContainer2 );
	}
}
   const S32 getElapsedMs()
   {
      if(mUsingPerfCounter)
      {
         // Use QPC, update remainders so we don't leak time, and return the elapsed time.
         QueryPerformanceCounter( (LARGE_INTEGER *) &mPerfCountNext);
         F64 elapsedF64 = (1000.0 * F64(mPerfCountNext - mPerfCountCurrent) / F64(mFrequency));
         elapsedF64 += mPerfCountRemainderCurrent;
         U32 elapsed = (U32)mFloor(elapsedF64);
         mPerfCountRemainderNext = elapsedF64 - F64(elapsed);

         return elapsed;
      }
      else
      {
         // Do something naive with GTC.
         mTickCountNext = GetTickCount();
         return mTickCountNext - mTickCountCurrent;
      }
   }
Beispiel #21
0
bool LightAnimData::AnimValue<COUNT>::animate(F32 time, F32 *output, bool multiply)
{
   F32 scaledTime, lerpFactor, valueRange, keyFrameLerp;
   U32 posFrom, posTo;
   S32 keyFrameFrom, keyFrameTo;
   F32 initialValue = *output;
   if (!multiply)
      initialValue = 1;

   bool wasAnimated = false;

   for ( U32 i=0; i < COUNT; i++ )
   {
      if ( mIsZero( timeScale[i] ) )
         continue;

      wasAnimated = true;

      scaledTime = mFmod( time, period[i] ) * timeScale[i];

	   posFrom = mFloor( scaledTime );
	   posTo = mCeil( scaledTime );

      keyFrameFrom = dToupper( keys[i][posFrom] ) - 65;
      keyFrameTo = dToupper( keys[i][posTo] ) - 65;
	   valueRange = ( value2[i] - value1[i] ) / 25.0f;

      if ( !smooth[i] )
         output[i] = (value1[i] + (keyFrameFrom * valueRange)) * initialValue;
      else
      {
         lerpFactor = scaledTime - posFrom;
   	   keyFrameLerp = ( keyFrameTo - keyFrameFrom ) * lerpFactor;

         output[i] = (value1[i] + ((keyFrameFrom + keyFrameLerp) * valueRange)) * initialValue;
      }
   }

   return wasAnimated;
}
void ProjectedShadow::_calcScore( const SceneRenderState *state )
{
    if ( !mDecalInstance )
        return;

    F32 pixRadius = mDecalInstance->calcPixelSize( state->getViewport().extent.y, state->getCameraPosition(), state->getWorldToScreenScale().y );

    F32 pct = pixRadius / mDecalInstance->mDataBlock->fadeStartPixelSize;

    U32 msSinceLastRender = Platform::getVirtualMilliseconds() - getLastRenderTime();

    ShapeBaseData *data = NULL;
    if ( mShapeBase )
        data = static_cast<ShapeBaseData*>( mShapeBase->getDataBlock() );

    // For every 1s this shadow hasn't been
    // updated we'll add 10 to the score.
    F32 secs = mFloor( (F32)msSinceLastRender / 1000.0f );

    mScore = pct + secs;
    mClampF( mScore, 0.0f, 2000.0f );
}
Beispiel #23
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();
}
void TransformTool::renderTool()
{
   if (!mActive)
      return;

   // Grid
   {
      Point3F editorPos = mEditorManager->mEditorCamera.getWorldPosition();
      editorPos = editorPos / 10.0f;
      editorPos.x = mFloor(editorPos.x);
      editorPos.y = mFloor(editorPos.y);
      editorPos = editorPos * 10.0f;

      Torque::Debug.ddPush();
      Torque::Debug.ddSetState(true, false, true);

      Torque::Debug.ddSetWireframe(true);
      Torque::Debug.ddSetColor(BGFXCOLOR_RGBA(255, 255, 255, 255));
      F32 gridNormal[3] = { 0.0f, 0.0f, 1.0f };
      F32 gridPos[3] = { editorPos.x, editorPos.y, -0.01f };
      Torque::Debug.ddDrawGrid(gridNormal, gridPos, 100, 10.0f);
   }

   // Draw Light Icons
   /*if (mLightIcon != NULL)
   {
      Vector<Lighting::LightData*> lightList = Torque::Lighting.getLightList();
      for (S32 n = 0; n < lightList.size(); ++n)
      {
         Lighting::LightData* light = lightList[n];

         Torque::Graphics.drawBillboard(mEditorManager->mRenderLayer4View->id,
                                              mLightIcon,
                                              light->position,
                                              1.0f, 1.0f,
                                              ColorI(light->color[0] * 255, light->color[1] * 255, light->color[2] * 255, 255),
                                              NULL);
      }
   }*/

   if (mMultiselect)
   {
      Box3F multiSelectBox;
      multiSelectBox.set(Point3F(0, 0, 0));
         
      for (S32 n = 0; n < mSelectedObjects.size(); ++n)
      {
         Scene::SceneObject* obj = dynamic_cast<Scene::SceneObject*>(mSelectedObjects[n]);
         if (obj)
         {
            if (n == 0)
               multiSelectBox = obj->mBoundingBox;
            else
               multiSelectBox.intersect(obj->mBoundingBox);
         }

         Scene::BaseComponent* component = dynamic_cast<Scene::BaseComponent*>(mSelectedObjects[n]);
         if (component)
         {
            Box3F boundingBox = component->getBoundingBox();
            boundingBox.transform(component->mTransform.matrix);

            if (n == 0)
               multiSelectBox = boundingBox;
            else
               multiSelectBox.intersect(boundingBox);
         }
      }

      mSelectionBounds        = true;
      mSelectionBoundsStart   = multiSelectBox.minExtents;
      mSelectionBoundsEnd     = multiSelectBox.maxExtents;
   }

   // Object Selected
   if (mSelectedObject != NULL && mSelectedComponent == NULL)
   {
      mSelectionBounds        = true;
      mSelectionBoundsStart   = mSelectedObject->mBoundingBox.minExtents;
      mSelectionBoundsEnd     = mSelectedObject->mBoundingBox.maxExtents;
   }

   // Component Selected
   if (mSelectedObject != NULL && mSelectedComponent != NULL)
   {
      Box3F boundingBox = mSelectedComponent->getBoundingBox();
      boundingBox.transform(mSelectedObject->mTransform.matrix);

      mSelectionBounds        = true;
      mSelectionBoundsStart   = boundingBox.minExtents;
      mSelectionBoundsEnd     = boundingBox.maxExtents;
   }

   // Selection Bounding Box
   if (mSelectionBounds)
   {
      Aabb debugBox;
      debugBox.m_min[0] = mSelectionBoundsStart.x;
      debugBox.m_min[1] = mSelectionBoundsStart.y;
      debugBox.m_min[2] = mSelectionBoundsStart.z;
      debugBox.m_max[0] = mSelectionBoundsEnd.x;
      debugBox.m_max[1] = mSelectionBoundsEnd.y;
      debugBox.m_max[2] = mSelectionBoundsEnd.z;

      Torque::Debug.ddSetWireframe(true);
      Torque::Debug.ddSetColor(BGFXCOLOR_RGBA(mSelectionBoundsColor.red, mSelectionBoundsColor.green, mSelectionBoundsColor.blue, mSelectionBoundsColor.alpha));
      Torque::Debug.ddDrawAabb(debugBox);

      Torque::Debug.ddPop();
   }

   // Gizmo
   mGizmo.render();

   // Debug
   if (mDebugWorldRay)
   {
      Torque::Debug.ddMoveTo(mLastRayStart.x, mLastRayStart.y, mLastRayStart.z);
      Torque::Debug.ddLineTo(mLastRayEnd.x, mLastRayEnd.y, mLastRayEnd.z);
   }

   if (mDebugBoxSelection)
   {
      for (U32 i = 0; i < 4; ++i)
      {
         Torque::Debug.ddMoveTo(mBoxNearPoint.x, mBoxNearPoint.y, mBoxNearPoint.z);
         Torque::Debug.ddLineTo(mBoxFarPoint[i].x, mBoxFarPoint[i].y, mBoxFarPoint[i].z);
      }
   }
}
Beispiel #25
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);
         }
      }
   }
}
Beispiel #26
0
bool GFXGLShader::_init()
{
   // Don't initialize empty shaders.
   if ( mVertexFile.isEmpty() && mPixelFile.isEmpty() )
      return false;

   clearShaders();

   mProgram = glCreateProgram();
   
   // Set the macros and add the global ones.
   Vector<GFXShaderMacro> macros;
   macros.merge( mMacros );
   macros.merge( smGlobalMacros );

   // Add the shader version to the macros.
   const U32 mjVer = (U32)mFloor( mPixVersion );
   const U32 mnVer = (U32)( ( mPixVersion - F32( mjVer ) ) * 10.01f );
   macros.increment();
   macros.last().name = "TORQUE_SM";
   macros.last().value = String::ToString( mjVer * 10 + mnVer );

   // Default to true so we're "successful" if a vertex/pixel shader wasn't specified.
   bool compiledVertexShader = true;
   bool compiledPixelShader = true;
   
   // Compile the vertex and pixel shaders if specified.
   if(!mVertexFile.isEmpty())
      compiledVertexShader = initShader(mVertexFile, true, macros);
   if(!mPixelFile.isEmpty())
      compiledPixelShader = initShader(mPixelFile, false, macros);
      
   // If either shader was present and failed to compile, bail.
   if(!compiledVertexShader || !compiledPixelShader)
      return false;

   // Link it!
   glLinkProgram( mProgram );

   GLint linkStatus;
   glGetProgramiv( mProgram, GL_LINK_STATUS, &linkStatus );
   
   // Dump the info log to the console
   U32 logLength = 0;
   glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, (GLint*)&logLength);
   if ( logLength )
   {
      FrameAllocatorMarker fam;
      char* log = (char*)fam.alloc( logLength );
      glGetProgramInfoLog( mProgram, logLength, NULL, log );

      if ( linkStatus == GL_FALSE )
      {
         if ( smLogErrors )
         {
            Con::errorf( "GFXGLShader::init - Error linking shader!" );
            Con::errorf( "Program %s / %s: %s", 
                mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), log);
         }
      }
      else if ( smLogWarnings )
      {
         Con::warnf( "Program %s / %s: %s", 
             mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), log);
      }
   }

   // If we failed to link, bail.
   if ( linkStatus == GL_FALSE )
      return false;

   initConstantDescs();   
   initHandles();
   
   // Notify Buffers we might have changed in size. 
   // If this was our first init then we won't have any activeBuffers 
   // to worry about unnecessarily calling.
   Vector<GFXShaderConstBuffer*>::iterator biter = mActiveBuffers.begin();
   for ( ; biter != mActiveBuffers.end(); biter++ )   
      ((GFXGLShaderConstBuffer*)(*biter))->onShaderReload( this );
   
   return true;
}
void LeapMotionFrame::copyFromFramePointables(const Leap::PointableList& pointables)
{
   // Set up Vectors
   mPointableValid.increment(mPointableCount);
   mPointableId.increment(mPointableCount);
   mPointableHandIndex.increment(mPointableCount);
   mPointableType.increment(mPointableCount);
   mPointableRawPos.increment(mPointableCount);
   mPointablePos.increment(mPointableCount);
   mPointableRot.increment(mPointableCount);
   mPointableRotQuat.increment(mPointableCount);
   mPointableLength.increment(mPointableCount);
   mPointableWidth.increment(mPointableCount);

   // Copy data
   for(U32 i=0; i<mPointableCount; ++i)
   {
      const Leap::Pointable& pointable = pointables[i];

      mPointableValid[i] = pointable.isValid();
      mPointableId[i] = pointable.id();
      mPointableLength[i] = pointable.length();
      mPointableWidth[i] = pointable.width();

      mPointableType[i] = PT_UNKNOWN;
      if(pointable.isFinger())
      {
         mPointableType[i] = PT_FINGER;
      }
      else if(pointable.isTool())
      {
         mPointableType[i] = PT_TOOL;
      }

      // Which hand, if any
      const Leap::Hand& hand = pointable.hand();
      if(hand.isValid())
      {
         bool found = false;
         S32 handId = hand.id();
         for(U32 j=0; j<mHandCount; ++j)
         {
            if(mHandId[j] == handId)
            {
               mPointableHandIndex[i] = j;
               found = true;
               break;
            }
         }

         if(!found)
         {
            mPointableHandIndex[i] = -1;
         }
      }
      else
      {
         mPointableHandIndex[i] = -1;
      }

      // Position
      LeapMotionUtil::convertPosition(pointable.tipPosition(), mPointableRawPos[i]);
      mPointablePos[i].x = (S32)mFloor(mPointableRawPos[i].x);
      mPointablePos[i].y = (S32)mFloor(mPointableRawPos[i].y);
      mPointablePos[i].z = (S32)mFloor(mPointableRawPos[i].z);

      // Rotation
      LeapMotionUtil::convertPointableRotation(pointable, mPointableRot[i]);
      mPointableRotQuat[i].set(mPointableRot[i]);
   }
}
Beispiel #28
0
bool ClipMap::fillWithTextureData()
{
   PROFILE_SCOPE(ClipMap_fillWithTextureData);

   mForceClipmapPurge = false;
   // Note our interest for the cache.
   {
      // Calculate the new texel at most detailed level.
      Point2F texelCenterF = mLevels[0].mClipCenter * F32(mClipMapSize) * mLevels[0].mScale;
      Point2I texelCenter((S32)mFloor(texelCenterF.y), (S32)mFloor(texelCenterF.x));

      // Update interest region.
      mImageCache->setInterestCenter(texelCenter);
   }

   // First generate our desired rects for each level.
   FrameTemp< RectI > desiredData( mClipStackDepth );
   for(S32 i=0; i<mClipStackDepth; i++)
   {
      ClipStackEntry &cse = mLevels[i];

      // Calculate new center point for this texture.
      Point2F texelCenterF = cse.mClipCenter * 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;
      //}

      desiredData[i] = RectI(texelTopLeft, Point2I(mClipMapSize, mClipMapSize));

      // Make sure we have available data...
      if(!mImageCache->isDataAvailable(getMipLevel(cse.mScale), desiredData[i]))
         return false;
   }

   // Upload all the textures...
   for(S32 i=0; i<mClipStackDepth; i++)
   {
      ClipStackEntry &cse = mLevels[i];

      RectI buffer[8];
      S32   rectCount = 0;

      clipAgainstGrid(mClipMapSize, desiredData[i], &rectCount, buffer);
      AssertFatal(rectCount < 8, "ClipMap::fillWithTextureData - got too many rects back!");

      if(rectCount)
      {
         if (!mImageCache->beginRectUpdates(cse))
         {
            mForceClipmapPurge = true;
            return false;
         }

         for(S32 j=0; j<rectCount; j++)
         {
            RectI srcRegion = buffer[j];
            buffer[j].point.x = srcRegion.point.x % mClipMapSize;
            buffer[j].point.y = srcRegion.point.y % mClipMapSize;

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

         mImageCache->finishRectUpdates(cse);
      }

      cse.mToroidalOffset  = desiredData[i].point;
   }
   
   GRAPHIC->disableShaders();

   // Success!
   return true;
}
void GuiTextEditCtrl::drawText( const RectI &drawRect, bool isFocused )
{
   StringBuffer textBuffer;
   Point2I drawPoint = drawRect.point;
   Point2I paddingLeftTop, paddingRightBottom;

   // Or else just copy it over.
   char *renderText = Con::getReturnBuffer( GuiTextEditCtrl::MAX_STRING_LENGTH );
   getRenderText( renderText );

   // Apply password masking (make the masking char optional perhaps?)
   if(mPasswordText)
   {
      const U32 renderLen = dStrlen( renderText );
      for( U32 i = 0; i < renderLen; i++ )
         textBuffer.append(mPasswordMask);
   }
   else
   {
       textBuffer.set( renderText );
   }

   // Just a little sanity.
   if(mCursorPos > textBuffer.length()) 
      mCursorPos = textBuffer.length();

   paddingLeftTop.set(( mProfile->mTextOffset.x != 0 ? mProfile->mTextOffset.x : 3 ), mProfile->mTextOffset.y);
   paddingRightBottom = paddingLeftTop;

   // Center vertically:
   drawPoint.y += ( ( drawRect.extent.y - paddingLeftTop.y - paddingRightBottom.y - S32( mProfile->mFont->getHeight() ) ) / 2 ) + paddingLeftTop.y;

   // Align horizontally:
   
   S32 textWidth = mProfile->mFont->getStrNWidth(textBuffer.getPtr(), textBuffer.length());

   switch( mProfile->mAlignment )
   {
   case GuiControlProfile::RightJustify:
      drawPoint.x += ( drawRect.extent.x - textWidth - paddingRightBottom.x );
      break;
   case GuiControlProfile::CenterJustify:
      drawPoint.x += ( ( drawRect.extent.x - textWidth ) / 2 );
      break;
   default:
   case GuiControlProfile::LeftJustify :
      drawPoint.x += paddingLeftTop.x;
      break;
   }

   ColorI fontColor = mActive ? mProfile->mFontColor : mProfile->mFontColorNA;

   // now draw the text
   Point2I cursorStart, cursorEnd;
   mTextOffset.y = drawPoint.y;
   mTextOffset.x = drawPoint.x;

   if ( drawRect.extent.x - paddingLeftTop.x > textWidth )
      mTextOffset.x = drawPoint.x;
   else
   {
      // Alignment affects large text
      if ( mProfile->mAlignment == GuiControlProfile::RightJustify
         || mProfile->mAlignment == GuiControlProfile::CenterJustify )
      {
         if ( mTextOffset.x + textWidth < (drawRect.point.x + drawRect.extent.x) - paddingRightBottom.x)
            mTextOffset.x = (drawRect.point.x + drawRect.extent.x) - paddingRightBottom.x - textWidth;
      }
   }

   // calculate the cursor
   if( isFocused && mActive )
   {
      // Where in the string are we?
      S32 cursorOffset=0, charWidth=0;
      UTF16 tempChar = textBuffer.getChar(mCursorPos);

      // Alright, we want to terminate things momentarily.
      if(mCursorPos > 0)
      {
         cursorOffset = mProfile->mFont->getStrNWidth(textBuffer.getPtr(), mCursorPos);
      }
      else
         cursorOffset = 0;

      if( tempChar && mProfile->mFont->isValidChar( tempChar ) )
         charWidth = mProfile->mFont->getCharWidth( tempChar );
      else
         charWidth = paddingRightBottom.x;

      if( mTextOffset.x + cursorOffset + 1 >= (drawRect.point.x + drawRect.extent.x) ) // +1 is for the cursor width
      {
         // Cursor somewhere beyond the textcontrol,
         // skip forward roughly 25% of the total width (if possible)
         S32 skipForward = drawRect.extent.x / 4 * 3;

         if ( cursorOffset + skipForward > textWidth )
            mTextOffset.x = (drawRect.point.x + drawRect.extent.x) - paddingRightBottom.x - textWidth;
         else
         {
            //mTextOffset.x -= skipForward;
            S32 mul = (S32)( mFloor( (cursorOffset-drawRect.extent.x) / skipForward ) );
            mTextOffset.x -= skipForward * mul + drawRect.extent.x - 1; // -1 is for the cursor width
         }
      }
      else if( mTextOffset.x + cursorOffset < drawRect.point.x + paddingLeftTop.x )
      {
         // Cursor somewhere before the textcontrol
         // skip backward roughly 25% of the total width (if possible)
         S32 skipBackward = drawRect.extent.x / 4 * 3;

         if ( cursorOffset - skipBackward < 0 )
            mTextOffset.x = drawRect.point.x + paddingLeftTop.x;
         else
         {
            S32 mul = (S32)( mFloor( cursorOffset / skipBackward ) );
            mTextOffset.x += drawRect.point.x - mTextOffset.x - skipBackward * mul;
         }
      }
      cursorStart.x = mTextOffset.x + cursorOffset;

#ifdef TORQUE_OS_MAC
      cursorStart.x += charWidth/2;
#endif
      
      cursorEnd.x = cursorStart.x;

      S32 cursorHeight = mProfile->mFont->getHeight();
      if ( cursorHeight < drawRect.extent.y )
      {
         cursorStart.y = drawPoint.y;
         cursorEnd.y = cursorStart.y + cursorHeight;
      }
      else
      {
         cursorStart.y = drawRect.point.y;
         cursorEnd.y = cursorStart.y + drawRect.extent.y;
      }
   }

   //draw the text
   if ( !isFocused )
      mBlockStart = mBlockEnd = 0;

   //also verify the block start/end
   if ((mBlockStart > textBuffer.length() || (mBlockEnd > textBuffer.length()) || (mBlockStart > mBlockEnd)))
      mBlockStart = mBlockEnd = 0;

   Point2I tempOffset = mTextOffset;

   //draw the portion before the highlight
   if ( mBlockStart > 0 )
   {
      GFX->getDrawUtil()->setBitmapModulation( fontColor );
      const UTF16* preString2 = textBuffer.getPtr();
      GFX->getDrawUtil()->drawText( mProfile->mFont, tempOffset, preString2, mProfile->mFontColors );
      tempOffset.x += mProfile->mFont->getStrNWidth(preString2, mBlockStart);
   }

   //draw the highlighted portion
   if ( mBlockEnd > 0 )
   {
      const UTF16* highlightBuff = textBuffer.getPtr() + mBlockStart;
      U32 highlightBuffLen = mBlockEnd-mBlockStart;

      S32 highlightWidth = mProfile->mFont->getStrNWidth(highlightBuff, highlightBuffLen);

      GFX->getDrawUtil()->drawRectFill( Point2I( tempOffset.x, drawRect.point.y ),
         Point2I( tempOffset.x + highlightWidth, drawRect.point.y + drawRect.extent.y - 1),
         mProfile->mFontColorSEL );

      GFX->getDrawUtil()->setBitmapModulation( mProfile->mFontColorHL );
      GFX->getDrawUtil()->drawTextN( mProfile->mFont, tempOffset, highlightBuff, highlightBuffLen, mProfile->mFontColors );
      tempOffset.x += highlightWidth;
   }

   //draw the portion after the highlight
   if(mBlockEnd < textBuffer.length())
   {
      const UTF16* finalBuff = textBuffer.getPtr() + mBlockEnd;
      U32 finalBuffLen = textBuffer.length() - mBlockEnd;

      GFX->getDrawUtil()->setBitmapModulation( fontColor );
      GFX->getDrawUtil()->drawTextN( mProfile->mFont, tempOffset, finalBuff, finalBuffLen, mProfile->mFontColors );
   }

   //draw the cursor
   if ( isFocused && mCursorOn )
      GFX->getDrawUtil()->drawLine( cursorStart, cursorEnd, mProfile->mCursorColor );
}
Beispiel #30
0
bool GFXGLShader::_init()
{
   PROFILE_SCOPE(GFXGLShader_Init);
   // Don't initialize empty shaders.
   if ( mVertexFile.isEmpty() && mPixelFile.isEmpty() )
      return false;

   clearShaders();

   mProgram = glCreateProgram();
   
   // Set the macros and add the global ones.
   Vector<GFXShaderMacro> macros;
   macros.merge( mMacros );
   macros.merge( smGlobalMacros );

   // Add the shader version to the macros.
   const U32 mjVer = (U32)mFloor( mPixVersion );
   const U32 mnVer = (U32)( ( mPixVersion - F32( mjVer ) ) * 10.01f );
   macros.increment();
   macros.last().name = "TORQUE_SM";
   macros.last().value = String::ToString( mjVer * 10 + mnVer );
   macros.increment();
   macros.last().name = "TORQUE_VERTEX_SHADER";
   macros.last().value = "";   

   // Default to true so we're "successful" if a vertex/pixel shader wasn't specified.
   bool compiledVertexShader = true;
   bool compiledPixelShader = true;
   
   // Compile the vertex and pixel shaders if specified.
   if(!mVertexFile.isEmpty())
      compiledVertexShader = initShader(mVertexFile, true, macros);

   macros.last().name = "TORQUE_PIXEL_SHADER";
   if(!mPixelFile.isEmpty())
      compiledPixelShader = initShader(mPixelFile, false, macros);
      
   // If either shader was present and failed to compile, bail.
   if(!compiledVertexShader || !compiledPixelShader)
      return false;

   //bind vertex attributes
   glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_Position,    "vPosition");
   glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_Normal,      "vNormal");
   glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_Color,       "vColor");
   glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_Tangent,     "vTangent");
   glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TangentW,    "vTangentW");
   glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_Binormal,    "vBinormal");
   glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord0,   "vTexCoord0");
   glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord1,   "vTexCoord1");
   glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord2,   "vTexCoord2");
   glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord3,   "vTexCoord3");
   glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord4,   "vTexCoord4");
   glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord5,   "vTexCoord5");
   glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord6,   "vTexCoord6");
   glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord7,   "vTexCoord7");
   glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord8,   "vTexCoord8");
   glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord9,   "vTexCoord9");

   //bind fragment out color
   glBindFragDataLocation(mProgram, 0, "OUT_col");
   glBindFragDataLocation(mProgram, 1, "OUT_col1");
   glBindFragDataLocation(mProgram, 2, "OUT_col2");
   glBindFragDataLocation(mProgram, 3, "OUT_col3");

   // Link it!
   glLinkProgram( mProgram );

   GLint linkStatus;
   glGetProgramiv( mProgram, GL_LINK_STATUS, &linkStatus );
   
   // Dump the info log to the console
   U32 logLength = 0;
   glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, (GLint*)&logLength);
   if ( logLength )
   {
      FrameAllocatorMarker fam;
      char* log = (char*)fam.alloc( logLength );
      glGetProgramInfoLog( mProgram, logLength, NULL, log );

      if ( linkStatus == GL_FALSE )
      {
         if ( smLogErrors )
         {
            Con::errorf( "GFXGLShader::init - Error linking shader!" );
            Con::errorf( "Program %s / %s: %s", 
                mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), log);
         }
      }
      else if ( smLogWarnings )
      {
         Con::warnf( "Program %s / %s: %s", 
             mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), log);
      }
   }

   // If we failed to link, bail.
   if ( linkStatus == GL_FALSE )
      return false;

   initConstantDescs();   
   initHandles();
   
   // Notify Buffers we might have changed in size. 
   // If this was our first init then we won't have any activeBuffers 
   // to worry about unnecessarily calling.
   Vector<GFXShaderConstBuffer*>::iterator biter = mActiveBuffers.begin();
   for ( ; biter != mActiveBuffers.end(); biter++ )   
      ((GFXGLShaderConstBuffer*)(*biter))->onShaderReload( this );
   
   return true;
}