void convertRotation(const F32 inRotMat[3][3], MatrixF& outRotation)
{
   // Set rotation.  We need to convert from sixense coordinates to
   // Torque coordinates.  The conversion is:
   //
   // Sixense                      Torque
   // a b c         a  b  c        a -c  b
   // d e f   -->  -g -h -i  -->  -g  i -h
   // g h i         d  e  f        d -f  e
   outRotation.setColumn(0, Point4F( inRotMat[0][0], -inRotMat[0][2],  inRotMat[0][1], 0.0f));
   outRotation.setColumn(1, Point4F(-inRotMat[2][0],  inRotMat[2][2], -inRotMat[2][1], 0.0f));
   outRotation.setColumn(2, Point4F( inRotMat[1][0], -inRotMat[1][2],  inRotMat[1][1], 0.0f));
   outRotation.setPosition(Point3F::Zero);
}
void WorldEditorSelection::offset( const Point3F& offset, F32 gridSnap )
{
   for( iterator iter = begin(); iter != end(); ++ iter )
   {
      SceneObject* obj = dynamic_cast<SceneObject*>( *iter );
      if( !obj )
         continue;

      MatrixF mat = obj->getTransform();
      Point3F wPos;
      mat.getColumn(3, &wPos);

      // adjust
      wPos += offset;
      
      if( gridSnap != 0.f )
      {
         wPos.x -= mFmod( wPos.x, gridSnap );
         wPos.y -= mFmod( wPos.y, gridSnap );
         wPos.z -= mFmod( wPos.z, gridSnap );
      }
      
      mat.setColumn(3, wPos);
      obj->setTransform(mat);
   }

   mCentroidValid = false;
}
Ejemplo n.º 3
0
void RigidBody::setRenderPosition(const Point3F& pos, const QuatF& rot)
{
	MatrixF mat;
	rot.setMatrix(&mat);
	mat.setColumn(3,pos);
	setRenderTransform(mat);
}
Ejemplo n.º 4
0
void Item::setTransform(const MatrixF& mat)
{
   Point3F pos;
   mat.getColumn(3,&pos);
   MatrixF tmat;
   if (!mRotate) {
      // Forces all rotation to be around the z axis
      VectorF vec;
      mat.getColumn(1,&vec);
      tmat.set(EulerF(0,0,-mAtan2(-vec.x,vec.y)));
   }
   else
      tmat.identity();
   tmat.setColumn(3,pos);
   Parent::setTransform(tmat);
   if (!mStatic)
   {
      mAtRest = false;
      mAtRestCounter = 0;
   }

   if ( mPhysicsRep )
      mPhysicsRep->setTransform( getTransform() );

   setMaskBits(RotationMask | PositionMask | NoWarpMask);
}
Ejemplo n.º 5
0
void SceneObject::setPosition(const Point3F &pos)
{
	AssertFatal( !mIsNaN( pos ), "SceneObject::setPosition() - The position is NaN!" );

   MatrixF xform = mObjToWorld;
   xform.setColumn(3, pos);
   setTransform(xform);
}
Ejemplo n.º 6
0
void convertPointableRotation(const Leap::Pointable& pointable, MatrixF& outRotation)
{
   // We need to convert from Motion coordinates to
   // Torque coordinates.  The conversion is:
   //
   // Motion                       Torque
   // a b c         a  b  c        a -c  b
   // d e f   -->  -g -h -i  -->  -g  i -h
   // g h i         d  e  f        d -f  e
   Leap::Vector pointableFront = -pointable.direction();
   Leap::Vector pointableRight = Leap::Vector::up().cross(pointableFront);
   Leap::Vector pointableUp = pointableFront.cross(pointableRight);

   outRotation.setColumn(0, Point4F(  pointableRight.x, -pointableRight.z,  pointableRight.y,  0.0f));
   outRotation.setColumn(1, Point4F( -pointableFront.x,  pointableFront.z, -pointableFront.y,  0.0f));
   outRotation.setColumn(2, Point4F(  pointableUp.x,    -pointableUp.z,     pointableUp.y,     0.0f));
   outRotation.setPosition(Point3F::Zero);
}
Ejemplo n.º 7
0
void Etherform::setRenderPosition(const Point3F& pos, const Point3F& rot, F32 dt)
{
   MatrixF xRot, zRot;
   xRot.set(EulerF(rot.x, 0, 0));
   zRot.set(EulerF(0, 0, rot.z));
   MatrixF temp;
   temp.mul(zRot, xRot);
   temp.setColumn(3, pos);
   Parent::setRenderTransform(temp);
}
Ejemplo n.º 8
0
void Item::interpolateTick(F32 dt)
{
   Parent::interpolateTick(dt);

   // Client side interpolation
   Point3F pos = delta.pos + delta.posVec * dt;
   MatrixF mat = mRenderObjToWorld;
   mat.setColumn(3,pos);
   setRenderTransform(mat);
   delta.dt = dt;
}
Ejemplo n.º 9
0
void convertHandRotation(const Leap::Hand& hand, MatrixF& outRotation)
{
   // We need to convert from Motion coordinates to
   // Torque coordinates.  The conversion is:
   //
   // Motion                       Torque
   // a b c         a  b  c        a -c  b
   // d e f   -->  -g -h -i  -->  -g  i -h
   // g h i         d  e  f        d -f  e
   const Leap::Vector& handToFingers = hand.direction();
   Leap::Vector handFront = -handToFingers;
   const Leap::Vector& handDown = hand.palmNormal();
   Leap::Vector handUp = -handDown;
   Leap::Vector handRight = handUp.cross(handFront);

   outRotation.setColumn(0, Point4F(  handRight.x, -handRight.z,  handRight.y,  0.0f));
   outRotation.setColumn(1, Point4F( -handFront.x,  handFront.z, -handFront.y,  0.0f));
   outRotation.setColumn(2, Point4F(  handUp.x,    -handUp.z,     handUp.y,     0.0f));
   outRotation.setPosition(Point3F::Zero);
}
Ejemplo n.º 10
0
MatrixF PlaneReflector::getFrustumClipProj( MatrixF &modelview )
{
   static MatrixF rotMat(EulerF( static_cast<F32>(M_PI / 2.f), 0.0, 0.0));
   static MatrixF invRotMat(EulerF( -static_cast<F32>(M_PI / 2.f), 0.0, 0.0));


   MatrixF revModelview = modelview;
   revModelview = rotMat * revModelview;  // add rotation to modelview because it needs to be removed from projection

   // rotate clip plane into modelview space
   Point4F clipPlane;
   Point3F pnt = refplane * -(refplane.d + 0.0 );
   Point3F norm = refplane;

   revModelview.mulP( pnt );
   revModelview.mulV( norm );
   norm.normalize();

   clipPlane.set( norm.x, norm.y, norm.z, -mDot( pnt, norm ) );


   // Manipulate projection matrix
   //------------------------------------------------------------------------
   MatrixF proj = GFX->getProjectionMatrix();
   proj.mul( invRotMat );  // reverse rotation imposed by Torque
   proj.transpose();       // switch to row-major order

   // Calculate the clip-space corner point opposite the clipping plane
   // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
   // transform it into camera space by multiplying it
   // by the inverse of the projection matrix
   Vector4F	q;
   q.x = sgn(clipPlane.x) / proj(0,0);
   q.y = sgn(clipPlane.y) / proj(1,1);
   q.z = -1.0F;
   q.w = ( 1.0F - proj(2,2) ) / proj(3,2);

   F32 a = 1.0 / (clipPlane.x * q.x + clipPlane.y * q.y + clipPlane.z * q.z + clipPlane.w * q.w);

   Vector4F c = clipPlane * a;

   // CodeReview [ags 1/23/08] Come up with a better way to deal with this.
   if(GFX->getAdapterType() == OpenGL)
      c.z += 1.0f;

   // Replace the third column of the projection matrix
   proj.setColumn( 2, c );
   proj.transpose(); // convert back to column major order
   proj.mul( rotMat );  // restore Torque rotation

   return proj;
}
Ejemplo n.º 11
0
void GFXGLDevice::setClipRect( const RectI &inRect )
{
   AssertFatal(mCurrentRT.isValid(), "GFXGLDevice::setClipRect - must have a render target set to do any rendering operations!");

   // Clip the rect against the renderable size.
   Point2I size = mCurrentRT->getSize();
   RectI maxRect(Point2I(0,0), size);
   mClip = inRect;
   mClip.intersect(maxRect);

   // Create projection matrix.  See http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/ortho.html
   const F32 left = mClip.point.x;
   const F32 right = mClip.point.x + mClip.extent.x;
   const F32 bottom = mClip.extent.y;
   const F32 top = 0.0f;
   const F32 nearPlane = 0.0f;
   const F32 farPlane = 1.0f;
   
   const F32 tx = -(right + left)/(right - left);
   const F32 ty = -(top + bottom)/(top - bottom);
   const F32 tz = -(farPlane + nearPlane)/(farPlane - nearPlane);
   
   static Point4F pt;
   pt.set(2.0f / (right - left), 0.0f, 0.0f, 0.0f);
   mProjectionMatrix.setColumn(0, pt);
   
   pt.set(0.0f, 2.0f/(top - bottom), 0.0f, 0.0f);
   mProjectionMatrix.setColumn(1, pt);
   
   pt.set(0.0f, 0.0f, -2.0f/(farPlane - nearPlane), 0.0f);
   mProjectionMatrix.setColumn(2, pt);
   
   pt.set(tx, ty, tz, 1.0f);
   mProjectionMatrix.setColumn(3, pt);
   
   // Translate projection matrix.
   static MatrixF translate(true);
   pt.set(0.0f, -mClip.point.y, 0.0f, 1.0f);
   translate.setColumn(3, pt);
   
   mProjectionMatrix *= translate;
   
   setMatrix(GFXMatrixProjection, mProjectionMatrix);
   
   MatrixF mTempMatrix(true);
   setViewMatrix( mTempMatrix );
   setWorldMatrix( mTempMatrix );

   // Set the viewport to the clip rect
   RectI viewport(mClip.point.x, mClip.point.y, mClip.extent.x, mClip.extent.y);
   setViewport(viewport);
}
Ejemplo n.º 12
0
void Item::processTick(const Move* move)
{
   Parent::processTick(move);

   //
   if (mCollisionObject && !--mCollisionTimeout)
      mCollisionObject = 0;

   // Warp to catch up to server
   if (delta.warpTicks > 0)
   {
      delta.warpTicks--;

      // Set new pos.
      MatrixF mat = mObjToWorld;
      mat.getColumn(3,&delta.pos);
      delta.pos += delta.warpOffset;
      mat.setColumn(3,delta.pos);
      Parent::setTransform(mat);

      // Backstepping
      delta.posVec.x = -delta.warpOffset.x;
      delta.posVec.y = -delta.warpOffset.y;
      delta.posVec.z = -delta.warpOffset.z;
   }
   else
   {
      if (isServerObject() && mAtRest && (mStatic == false && mDataBlock->sticky == false))
      {
         if (++mAtRestCounter > csmAtRestTimer)
         {
            mAtRest = false;
            mAtRestCounter = 0;
            setMaskBits(PositionMask);
         }
      }

      if (!mStatic && !mAtRest && isHidden() == false)
      {
         updateVelocity(TickSec);
         updateWorkingCollisionSet(isGhost() ? sClientCollisionMask : sServerCollisionMask, TickSec);
         updatePos(isGhost() ? sClientCollisionMask : sServerCollisionMask, TickSec);
      }
      else
      {
         // Need to clear out last updatePos or warp interpolation
         delta.posVec.set(0,0,0);
      }
   }
}
Ejemplo n.º 13
0
bool Item::buildPolyList(PolyListContext context, AbstractPolyList* polyList, const Box3F&, const SphereF&)
{
   if ( context == PLC_Decal )
      return false;

   // Collision with the item is always against the item's object
   // space bounding box axis aligned in world space.
   Point3F pos;
   mObjToWorld.getColumn(3,&pos);
   IMat.setColumn(3,pos);
   polyList->setTransform(&IMat, mObjScale);
   polyList->setObject(this);
   polyList->addBox(mObjBox);
   return true;
}
Ejemplo n.º 14
0
void RigidBody::processTick(const Move* move)
{     
	Parent::processTick(move);

	if (mPhysShape)
	{
		// Save current interpolation
/*
		MatrixF curTr = getRenderTransform();
		mDelta.posVec = curTr.getPosition();
		mDelta.rot[0].set(curTr);
*/
		mDelta.posVec = mPhysPosition;
		mDelta.rot[0] = mPhysRotation;

		mPhysPosition	= mPhysShape->getPosition();
		mPhysRotation	= mPhysShape->getRotation();
		mForce			= mPhysShape->getForce();
		mTorque			= mPhysShape->getTorque();
		mLinVelocity	= mPhysShape->getLinVelocity();
		mAngVelocity	= mPhysShape->getAngVelocity();

		mDelta.pos     = mPhysPosition;
		mDelta.posVec -= mDelta.pos;
		mDelta.rot[1]  = mPhysRotation;

		// Update container database
		//setPosition(mDelta.pos, mDelta.rot[1]);
		MatrixF mat;
		mDelta.rot[1].setMatrix(&mat);
		mat.setColumn(3,mDelta.pos);
		Parent::setTransform(mat);
	}
/*
	Con::printf("ProcessTick s:%d vel: %f %f %f momentum: %f %f %f ",isServerObject(),mLinVelocity.x,mLinVelocity.y,mLinVelocity.z,
		mForce.x, mForce.y, mForce.z);
*/

	setMaskBits(PositionMask);
	updateContainer();
}
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.º 16
0
void EditTSCtrl::renderCameraAxis()
{
   GFXDEBUGEVENT_SCOPE( Editor_renderCameraAxis, ColorI::WHITE );

   static MatrixF sRotMat(EulerF( (M_PI_F / -2.0f), 0.0f, 0.0f));

   MatrixF camMat = mLastCameraQuery.cameraMatrix;
   camMat.mul(sRotMat);
   camMat.inverse();

   MatrixF axis;
   axis.setColumn(0, Point3F(1, 0, 0));
   axis.setColumn(1, Point3F(0, 0, 1));
   axis.setColumn(2, Point3F(0, -1, 0));
   axis.mul(camMat);

   Point3F forwardVec, upVec, rightVec;
	axis.getColumn( 2, &forwardVec );
	axis.getColumn( 1, &upVec );
	axis.getColumn( 0, &rightVec );

   Point2I pos = getPosition();
	F32 offsetx = pos.x + 20.0;
	F32 offsety = pos.y + getExtent().y - 42.0; // Take the status bar into account
	F32 scale = 15.0;

   // Generate correct drawing order
   ColorI c1(255,0,0);
   ColorI c2(0,255,0);
   ColorI c3(0,0,255);
	ColorI tc;
	Point3F *p1, *p2, *p3, *tp;
	p1 = &rightVec;
	p2 = &upVec;
	p3 = &forwardVec;
	if(p3->y > p2->y)
	{
		tp = p2; tc = c2;
		p2 = p3; c2 = c3;
		p3 = tp; c3 = tc;
	}
	if(p2->y > p1->y)
	{
		tp = p1; tc = c1;
		p1 = p2; c1 = c2;
		p2 = tp; c2 = tc;
	}

   PrimBuild::begin( GFXLineList, 6 );
		//*** Axis 1
		PrimBuild::color(c1);
		PrimBuild::vertex3f(offsetx, offsety, 0);
		PrimBuild::vertex3f(offsetx+p1->x*scale, offsety-p1->z*scale, 0);

		//*** Axis 2
		PrimBuild::color(c2);
		PrimBuild::vertex3f(offsetx, offsety, 0);
		PrimBuild::vertex3f(offsetx+p2->x*scale, offsety-p2->z*scale, 0);

		//*** Axis 3
		PrimBuild::color(c3);
		PrimBuild::vertex3f(offsetx, offsety, 0);
		PrimBuild::vertex3f(offsetx+p3->x*scale, offsety-p3->z*scale, 0);
   PrimBuild::end();
}
Ejemplo n.º 17
0
void Item::updatePos(const U32 /*mask*/, const F32 dt)
{
   // Try and move
   Point3F pos;
   mObjToWorld.getColumn(3,&pos);
   delta.posVec = pos;

   bool contact = false;
   bool nonStatic = false;
   bool stickyNotify = false;
   CollisionList collisionList;
   F32 time = dt;

   static Polyhedron sBoxPolyhedron;
   static ExtrudedPolyList sExtrudedPolyList;
   static EarlyOutPolyList sEarlyOutPolyList;
   MatrixF collisionMatrix(true);
   Point3F end = pos + mVelocity * time;
   U32 mask = isServerObject() ? sServerCollisionMask : sClientCollisionMask;

   // Part of our speed problem here is that we don't track contact surfaces, like we do
   //  with the player.  In order to handle the most common and performance impacting
   //  instance of this problem, we'll use a ray cast to detect any contact surfaces below
   //  us.  This won't be perfect, but it only needs to catch a few of these to make a
   //  big difference.  We'll cast from the top center of the bounding box at the tick's
   //  beginning to the bottom center of the box at the end.
   Point3F startCast((mObjBox.minExtents.x + mObjBox.maxExtents.x) * 0.5,
                     (mObjBox.minExtents.y + mObjBox.maxExtents.y) * 0.5,
                     mObjBox.maxExtents.z);
   Point3F endCast((mObjBox.minExtents.x + mObjBox.maxExtents.x) * 0.5,
                   (mObjBox.minExtents.y + mObjBox.maxExtents.y) * 0.5,
                   mObjBox.minExtents.z);
   collisionMatrix.setColumn(3, pos);
   collisionMatrix.mulP(startCast);
   collisionMatrix.setColumn(3, end);
   collisionMatrix.mulP(endCast);
   RayInfo rinfo;
   bool doToughCollision = true;
   disableCollision();
   if (mCollisionObject)
      mCollisionObject->disableCollision();
   if (getContainer()->castRay(startCast, endCast, mask, &rinfo))
   {
      F32 bd = -mDot(mVelocity, rinfo.normal);

      if (bd >= 0.0)
      {
         // Contact!
         if (mDataBlock->sticky && rinfo.object->getTypeMask() & (STATIC_COLLISION_TYPEMASK)) {
            mVelocity.set(0, 0, 0);
            mAtRest = true;
            mAtRestCounter = 0;
            stickyNotify = true;
            mStickyCollisionPos    = rinfo.point;
            mStickyCollisionNormal = rinfo.normal;
            doToughCollision = false;;
         } else {
            // Subtract out velocity into surface and friction
            VectorF fv = mVelocity + rinfo.normal * bd;
            F32 fvl = fv.len();
            if (fvl) {
               F32 ff = bd * mDataBlock->friction;
               if (ff < fvl) {
                  fv *= ff / fvl;
                  fvl = ff;
               }
            }
            bd *= 1 + mDataBlock->elasticity;
            VectorF dv = rinfo.normal * (bd + 0.002);
            mVelocity += dv;
            mVelocity -= fv;

            // Keep track of what we hit
            contact = true;
            U32 typeMask = rinfo.object->getTypeMask();
            if (!(typeMask & StaticObjectType))
               nonStatic = true;
            if (isServerObject() && (typeMask & ShapeBaseObjectType)) {
               ShapeBase* col = static_cast<ShapeBase*>(rinfo.object);
               queueCollision(col,mVelocity - col->getVelocity());
            }
         }
      }
   }
   enableCollision();
   if (mCollisionObject)
      mCollisionObject->enableCollision();

   if (doToughCollision)
   {
      U32 count;
      for (count = 0; count < 3; count++)
      {
         // Build list from convex states here...
         end = pos + mVelocity * time;


         collisionMatrix.setColumn(3, end);
         Box3F wBox = getObjBox();
         collisionMatrix.mul(wBox);
         Box3F testBox = wBox;
         Point3F oldMin = testBox.minExtents;
         Point3F oldMax = testBox.maxExtents;
         testBox.minExtents.setMin(oldMin + (mVelocity * time));
         testBox.maxExtents.setMin(oldMax + (mVelocity * time));

         sEarlyOutPolyList.clear();
         sEarlyOutPolyList.mNormal.set(0,0,0);
         sEarlyOutPolyList.mPlaneList.setSize(6);
         sEarlyOutPolyList.mPlaneList[0].set(wBox.minExtents,VectorF(-1,0,0));
         sEarlyOutPolyList.mPlaneList[1].set(wBox.maxExtents,VectorF(0,1,0));
         sEarlyOutPolyList.mPlaneList[2].set(wBox.maxExtents,VectorF(1,0,0));
         sEarlyOutPolyList.mPlaneList[3].set(wBox.minExtents,VectorF(0,-1,0));
         sEarlyOutPolyList.mPlaneList[4].set(wBox.minExtents,VectorF(0,0,-1));
         sEarlyOutPolyList.mPlaneList[5].set(wBox.maxExtents,VectorF(0,0,1));

         CollisionWorkingList& eorList = mConvex.getWorkingList();
         CollisionWorkingList* eopList = eorList.wLink.mNext;
         while (eopList != &eorList) {
            if ((eopList->mConvex->getObject()->getTypeMask() & mask) != 0)
            {
               Box3F convexBox = eopList->mConvex->getBoundingBox();
               if (testBox.isOverlapped(convexBox))
               {
                  eopList->mConvex->getPolyList(&sEarlyOutPolyList);
                  if (sEarlyOutPolyList.isEmpty() == false)
                     break;
               }
            }
            eopList = eopList->wLink.mNext;
         }
         if (sEarlyOutPolyList.isEmpty())
         {
            pos = end;
            break;
         }

         collisionMatrix.setColumn(3, pos);
         sBoxPolyhedron.buildBox(collisionMatrix, mObjBox, true);

         // Build extruded polyList...
         VectorF vector = end - pos;
         sExtrudedPolyList.extrude(sBoxPolyhedron, vector);
         sExtrudedPolyList.setVelocity(mVelocity);
         sExtrudedPolyList.setCollisionList(&collisionList);

         CollisionWorkingList& rList = mConvex.getWorkingList();
         CollisionWorkingList* pList = rList.wLink.mNext;
         while (pList != &rList) {
            if ((pList->mConvex->getObject()->getTypeMask() & mask) != 0)
            {
               Box3F convexBox = pList->mConvex->getBoundingBox();
               if (testBox.isOverlapped(convexBox))
               {
                  pList->mConvex->getPolyList(&sExtrudedPolyList);
               }
            }
            pList = pList->wLink.mNext;
         }

         if (collisionList.getTime() < 1.0)
         {
            // Set to collision point
            F32 dt = time * collisionList.getTime();
            pos += mVelocity * dt;
            time -= dt;

            // Pick the most resistant surface
            F32 bd = 0;
            const Collision* collision = 0;
            for (int c = 0; c < collisionList.getCount(); c++) {
               const Collision &cp = collisionList[c];
               F32 dot = -mDot(mVelocity,cp.normal);
               if (dot > bd) {
                  bd = dot;
                  collision = &cp;
               }
            }

            if (collision && mDataBlock->sticky && collision->object->getTypeMask() & (STATIC_COLLISION_TYPEMASK)) {
               mVelocity.set(0, 0, 0);
               mAtRest = true;
               mAtRestCounter = 0;
               stickyNotify = true;
               mStickyCollisionPos    = collision->point;
               mStickyCollisionNormal = collision->normal;
               break;
            } else {
               // Subtract out velocity into surface and friction
               if (collision) {
                  VectorF fv = mVelocity + collision->normal * bd;
                  F32 fvl = fv.len();
                  if (fvl) {
                     F32 ff = bd * mDataBlock->friction;
                     if (ff < fvl) {
                        fv *= ff / fvl;
                        fvl = ff;
                     }
                  }
                  bd *= 1 + mDataBlock->elasticity;
                  VectorF dv = collision->normal * (bd + 0.002);
                  mVelocity += dv;
                  mVelocity -= fv;

                  // Keep track of what we hit
                  contact = true;
                  U32 typeMask = collision->object->getTypeMask();
                  if (!(typeMask & StaticObjectType))
                     nonStatic = true;
                  if (isServerObject() && (typeMask & ShapeBaseObjectType)) {
                     ShapeBase* col = static_cast<ShapeBase*>(collision->object);
                     queueCollision(col,mVelocity - col->getVelocity());
                  }
               }
            }
         }
         else
         {
            pos = end;
            break;
         }
      }
      if (count == 3)
      {
         // Couldn't move...
         mVelocity.set(0, 0, 0);
      }
   }

   // If on the client, calculate delta for backstepping
   if (isGhost()) {
      delta.pos     = pos;
      delta.posVec -= pos;
      delta.dt = 1;
   }

   // Update transform
   MatrixF mat = mObjToWorld;
   mat.setColumn(3,pos);
   Parent::setTransform(mat);
   enableCollision();
   if (mCollisionObject)
      mCollisionObject->enableCollision();
   updateContainer();

   if ( mPhysicsRep )
      mPhysicsRep->setTransform( mat );

   //
   if (contact) {
      // Check for rest condition
      if (!nonStatic && mVelocity.len() < sAtRestVelocity) {
         mVelocity.x = mVelocity.y = mVelocity.z = 0;
         mAtRest = true;
         mAtRestCounter = 0;
      }

      // Only update the client if we hit a non-static shape or
      // if this is our final rest pos.
      if (nonStatic || mAtRest)
         setMaskBits(PositionMask);
   }

   // Collision callbacks. These need to be processed whether we hit
   // anything or not.
   if (!isGhost())
   {
      SimObjectPtr<Item> safePtr(this);
      if (stickyNotify)
      {
         notifyCollision();
         if(bool(safePtr))
			 onStickyCollision_callback( getIdString() );
      }
      else
         notifyCollision();

      // water
      if(bool(safePtr))
      {
         if(!mInLiquid && mWaterCoverage != 0.0f)
         {
            mInLiquid = true;
            if ( !isGhost() )
             mDataBlock->onEnterLiquid_callback( this, mWaterCoverage, mLiquidType.c_str() );
         }

         else if(mInLiquid && mWaterCoverage == 0.0f)
         {
            mInLiquid = false;
            if ( !isGhost() )
             mDataBlock->onLeaveLiquid_callback( this, mLiquidType.c_str() );
         }
      }
   }
}
Ejemplo n.º 18
0
void Item::unpackUpdate(NetConnection *connection, BitStream *stream)
{
   Parent::unpackUpdate(connection,stream);

   // InitialUpdateMask
   if (stream->readFlag()) {
      mRotate = stream->readFlag();
      mStatic = stream->readFlag();
      if (stream->readFlag())
         mathRead(*stream, &mObjScale);
      else
         mObjScale.set(1, 1, 1);
   }

   // ThrowSrcMask && mCollisionObject
   if (stream->readFlag()) {
      S32 gIndex = stream->readInt(NetConnection::GhostIdBitSize);
      setCollisionTimeout(static_cast<ShapeBase*>(connection->resolveGhost(gIndex)));
   }

   MatrixF mat = mObjToWorld;

   // RotationMask && !mRotate
   if (stream->readFlag()) {
      // Assumes rotation is about the Z axis
      AngAxisF aa;
      aa.axis.set(0.0f, 0.0f, stream->readFlag() ? -1.0f : 1.0f);
      stream->read(&aa.angle);
      aa.setMatrix(&mat);
      Point3F pos;
      mObjToWorld.getColumn(3,&pos);
      mat.setColumn(3,pos);
   }

   // PositionMask
   if (stream->readFlag()) {
      Point3F pos;
      mathRead(*stream, &pos);
      F32 speed = mVelocity.len();
      if ((mAtRest = stream->readFlag()) == true)
         mVelocity.set(0.0f, 0.0f, 0.0f);
      else
         mathRead(*stream, &mVelocity);

      if (stream->readFlag() && isProperlyAdded()) {
         // Determin number of ticks to warp based on the average
         // of the client and server velocities.
         delta.warpOffset = pos - delta.pos;
         F32 as = (speed + mVelocity.len()) * 0.5f * TickSec;
         F32 dt = (as > 0.00001f) ? delta.warpOffset.len() / as: sMaxWarpTicks;
         delta.warpTicks = (S32)((dt > sMinWarpTicks)? getMax(mFloor(dt + 0.5f), 1.0f): 0.0f);

         if (delta.warpTicks)
         {
            // Setup the warp to start on the next tick, only the
            // object's position is warped.
            if (delta.warpTicks > sMaxWarpTicks)
               delta.warpTicks = sMaxWarpTicks;
            delta.warpOffset /= (F32)delta.warpTicks;
         }
         else {
            // Going to skip the warp, server and client are real close.
            // Adjust the frame interpolation to move smoothly to the
            // new position within the current tick.
            Point3F cp = delta.pos + delta.posVec * delta.dt;
            VectorF vec = delta.pos - cp;
            F32 vl = vec.len();
            if (vl) {
               F32 s = delta.posVec.len() / vl;
               delta.posVec = (cp - pos) * s;
            }
            delta.pos = pos;
            mat.setColumn(3,pos);
         }
      }
      else {
         // Set the item to the server position
         delta.warpTicks = 0;
         delta.posVec.set(0,0,0);
         delta.pos = pos;
         delta.dt = 0;
         mat.setColumn(3,pos);
      }
   }
   Parent::setTransform(mat);
}
Ejemplo n.º 19
0
void TurretShape::_updateNodes(const Point3F& rot)
{
   EulerF xRot(rot.x, 0.0f, 0.0f);
   EulerF zRot(0.0f, 0.0f, rot.z);

   // Set heading
   S32 node = mDataBlock->headingNode;
   if (node != -1)
   {
      MatrixF* mat = &mShapeInstance->mNodeTransforms[node];
      Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node];
      Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node];

      QuatF qrot(zRot);
      qrot *= defaultRot.getQuatF();
      qrot.setMatrix( mat );      
      mat->setColumn(3, defaultPos);
   }

   // Set pitch
   node = mDataBlock->pitchNode;
   if (node != -1)
   {
      MatrixF* mat = &mShapeInstance->mNodeTransforms[node];
      Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node];
      Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node];

      QuatF qrot(xRot);
      qrot *= defaultRot.getQuatF();
      qrot.setMatrix( mat );    
      mat->setColumn(3, defaultPos);
   }

   // Now the mirror direction nodes, if any
   for (U32 i=0; i<TurretShapeData::NumMirrorDirectionNodes; ++i)
   {
      node = mDataBlock->pitchNodes[i];
      if (node != -1)
      {
         MatrixF* mat = &mShapeInstance->mNodeTransforms[node];
         Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node];
         Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node];         

         QuatF qrot(xRot);
         qrot *= defaultRot.getQuatF();
         qrot.setMatrix( mat );    
         mat->setColumn(3, defaultPos);
      }

      node = mDataBlock->headingNodes[i];
      if (node != -1)
      {
         MatrixF* mat = &mShapeInstance->mNodeTransforms[node];
         Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node];
         Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node];

         QuatF qrot(zRot);
         qrot *= defaultRot.getQuatF();
         qrot.setMatrix( mat );      
         mat->setColumn(3, defaultPos);
      }
   }

   mShapeInstance->setDirty(TSShapeInstance::TransformDirty);
}
Ejemplo n.º 20
0
/**
 * This method gets the move list for an object, in the case
 * of the AI, it actually calculates the moves, and then
 * sends them down the pipe.
 *
 * @param movePtr Pointer to move the move list into
 * @param numMoves Number of moves in the move list
 */
U32 AIClient::getMoveList( Move **movePtr,U32 *numMoves ) {
   //initialize the move structure and return pointers
   mMove = NullMove;
   *movePtr = &mMove;
   *numMoves = 1;

   // Check if we got a player
   mPlayer = NULL;
   mPlayer = dynamic_cast<Player *>( getControlObject() );

   // We got a something controling us?
   if( !mPlayer )
      return 1;

   
   // What is The Matrix?
   MatrixF moveMatrix;
   moveMatrix.set( EulerF( 0, 0, 0 ) );
   moveMatrix.setColumn( 3, Point3F( 0, 0, 0 ) );
   moveMatrix.transpose();
      
   // Position / rotation variables
   F32 curYaw, curPitch;
   F32 newYaw, newPitch;
   F32 xDiff, yDiff;

   
   F32 moveSpeed = mMoveSpeed;

   switch( mMoveMode ) {

   case ModeStop:
      return 1;     // Stop means no action
      break;

   case ModeStuck:
      // Fall through, so we still try to move
   case ModeMove:
   
      // Get my location
      MatrixF const& myTransform = mPlayer->getTransform();
      myTransform.getColumn( 3, &mLocation );
   
      // Set rotation variables
      Point3F rotation = mPlayer->getRotation();
      Point3F headRotation = mPlayer->getHeadRotation();
      curYaw = rotation.z;
      curPitch = headRotation.x;
      xDiff = mAimLocation.x - mLocation.x;
      yDiff = mAimLocation.y - mLocation.y;
   
      // first do Yaw
      if( !mIsZero( xDiff ) || !mIsZero( yDiff ) ) {
         // use the cur yaw between -Pi and Pi
         while( curYaw > M_2PI_F )
            curYaw -= M_2PI_F;
         while( curYaw < -M_2PI_F )
            curYaw += M_2PI_F;
      
         // find the new yaw
         newYaw = mAtan2( xDiff, yDiff );
      
         // find the yaw diff 
         F32 yawDiff = newYaw - curYaw;
      
         // make it between 0 and 2PI
         if( yawDiff < 0.0f )
            yawDiff += M_2PI_F;
         else if( yawDiff >= M_2PI_F )
            yawDiff -= M_2PI_F;
      
         // now make sure we take the short way around the circle
         if( yawDiff > M_2PI_F )
            yawDiff -= M_2PI_F;
         else if( yawDiff < -M_2PI_F )
            yawDiff += M_2PI_F;
      
         mMove.yaw = yawDiff;
      
         // set up the movement matrix
         moveMatrix.set( EulerF( 0.0f, 0.0f, newYaw ) );
      }
      else
         moveMatrix.set( EulerF( 0.0f, 0.0f, curYaw ) );
   
      // next do pitch
      F32 horzDist = Point2F( mAimLocation.x, mAimLocation.y ).len();

      if( !mIsZero( horzDist ) ) {
         //we shoot from the gun, not the eye...
         F32 vertDist = mAimLocation.z;
      
         newPitch = mAtan2( horzDist, vertDist ) - ( M_2PI_F / 2.0f );
      
         F32 pitchDiff = newPitch - curPitch;
         mMove.pitch = pitchDiff;
      }
   
      // finally, mMove towards mMoveDestination
      xDiff = mMoveDestination.x - mLocation.x;
      yDiff = mMoveDestination.y - mLocation.y;


      // Check if we should mMove, or if we are 'close enough'
      if( ( ( mFabs( xDiff ) > mMoveTolerance ) || 
            ( mFabs( yDiff ) > mMoveTolerance ) ) && ( !mIsZero( mMoveSpeed ) ) )
      {
         if( mIsZero( xDiff ) )
            mMove.y = ( mLocation.y > mMoveDestination.y ? -moveSpeed : moveSpeed );
         else if( mIsZero( yDiff ) )
            mMove.x = ( mLocation.x > mMoveDestination.x ? -moveSpeed : moveSpeed );
         else if( mFabs( xDiff ) > mFabs( yDiff ) ) {
            F32 value = mFabs( yDiff / xDiff ) * mMoveSpeed;
            mMove.y = ( mLocation.y > mMoveDestination.y ? -value : value );
            mMove.x = ( mLocation.x > mMoveDestination.x ? -moveSpeed : moveSpeed );
         }
         else {
            F32 value = mFabs( xDiff / yDiff ) * mMoveSpeed;
            mMove.x = ( mLocation.x > mMoveDestination.x ? -value : value );
            mMove.y = ( mLocation.y > mMoveDestination.y ? -moveSpeed : moveSpeed );
         }
      
         //now multiply the mMove vector by the transpose of the object rotation matrix
         moveMatrix.transpose();
         Point3F newMove;
         moveMatrix.mulP( Point3F( mMove.x, mMove.y, 0.0f ), &newMove );
      
         //and sub the result back in the mMove structure
         mMove.x = newMove.x;
         mMove.y = newMove.y;

         // We should check to see if we are stuck...
         if( mLocation.x == mLastLocation.x && 
             mLocation.y == mLastLocation.y &&
             mLocation.z == mLastLocation.z ) {

            // We're stuck...probably
            setMoveMode( ModeStuck );
         }
         else
            setMoveMode( ModeMove );
      }
      else {
         // Ok, we are close enough, lets stop

         // setMoveMode( ModeStop ); // DON'T use this, it'll throw the wrong callback
         mMoveMode = ModeStop;
         throwCallback(  "onReachDestination" ); // Callback

      }
      break;
   }

   // Test for target location in sight
   RayInfo dummy;
   Point3F targetLoc = mMoveDestination; // Change this

   if( mPlayer ) {
      if( !mPlayer->getContainer()->castRay( mLocation, targetLoc, 
                                                StaticShapeObjectType | StaticObjectType |
                                                TerrainObjectType, &dummy ) ) {
         if( !mTargetInLOS )
            throwCallback( "onTargetEnterLOS" );
      }
      else {
         if( mTargetInLOS )
            throwCallback( "onTargetExitLOS" );
            
      }
   }
   
   // Copy over the trigger status
   for( int i = 0; i < MaxTriggerKeys; i++ ) {
      mMove.trigger[i] = mTriggers[i];
      mTriggers[i] = false;
   }

   return 1;
}
void WorldEditorSelection::rotate(const EulerF & rot, const Point3F & center)
{
   // single selections will rotate around own axis, multiple about world
   if(size() == 1)
   {
      SceneObject* object = dynamic_cast< SceneObject* >( at( 0 ) );
      if( object )
      {
         MatrixF mat = object->getTransform();

         Point3F pos;
         mat.getColumn(3, &pos);

         // get offset in obj space
         Point3F offset = pos - center;
         MatrixF wMat = object->getWorldTransform();
         wMat.mulV(offset);

         //
         MatrixF transform(EulerF(0,0,0), -offset);
         transform.mul(MatrixF(rot));
         transform.mul(MatrixF(EulerF(0,0,0), offset));
         mat.mul(transform);

         object->setTransform(mat);
      }
   }
   else
   {
      for( iterator iter = begin(); iter != end(); ++ iter )
      {
         SceneObject* object = dynamic_cast< SceneObject* >( *iter );
         if( !object )
            continue;
            
         MatrixF mat = object->getTransform();

         Point3F pos;
         mat.getColumn(3, &pos);

         // get offset in obj space
         Point3F offset = pos - center;

         MatrixF transform(rot);
         Point3F wOffset;
         transform.mulV(offset, &wOffset);

         MatrixF wMat = object->getWorldTransform();
         wMat.mulV(offset);

         //
         transform.set(EulerF(0,0,0), -offset);

         mat.setColumn(3, Point3F(0,0,0));
         wMat.setColumn(3, Point3F(0,0,0));

         transform.mul(wMat);
         transform.mul(MatrixF(rot));
         transform.mul(mat);
         mat.mul(transform);

         mat.normalize();
         mat.setColumn(3, wOffset + center);

         object->setTransform(mat);
      }
   }

   mCentroidValid = false;
}
void DualParaboloidLightShadowMap::_render(  RenderPassManager* renderPass,
                                             const SceneRenderState *diffuseState )
{
   PROFILE_SCOPE(DualParaboloidLightShadowMap_render);

   const ShadowMapParams *p = mLight->getExtended<ShadowMapParams>();
   const LightMapParams *lmParams = mLight->getExtended<LightMapParams>();
   const bool bUseLightmappedGeometry = lmParams ? !lmParams->representedInLightmap || lmParams->includeLightmappedGeometryInShadow : true;

   const U32 texSize = getBestTexSize( 2 );

   if (  mShadowMapTex.isNull() || 
         mTexSize != texSize )
   {
      mTexSize = texSize;

      mShadowMapTex.set(   mTexSize * 2, mTexSize, 
                           ShadowMapFormat, &ShadowMapProfile, 
                           "DualParaboloidLightShadowMap" );
      mShadowMapDepth = _getDepthTarget( mShadowMapTex->getWidth(), mShadowMapTex->getHeight() );
   }

   GFXFrustumSaver frustSaver;
   GFXTransformSaver saver;   

   // Set and Clear target
   GFX->pushActiveRenderTarget();

   mTarget->attachTexture(GFXTextureTarget::Color0, mShadowMapTex);
   mTarget->attachTexture( GFXTextureTarget::DepthStencil, mShadowMapDepth );
   GFX->setActiveRenderTarget(mTarget);
   GFX->clear(GFXClearTarget | GFXClearStencil | GFXClearZBuffer, ColorI::WHITE, 1.0f, 0);

   const bool bUseSinglePassDPM = (p->shadowType == ShadowType_DualParaboloidSinglePass);

   // Set up matrix and visible distance
   mWorldToLightProj = mLight->getTransform();
   mWorldToLightProj.inverse();

   const F32 &lightRadius = mLight->getRange().x;
   const F32 paraboloidNearPlane = 0.01f;
   const F32 renderPosOffset = 0.01f;
   
   // Alter for creation of scene state if this is a single pass map
   if(bUseSinglePassDPM)
   {
      VectorF camDir;
      MatrixF temp = mLight->getTransform();
      temp.getColumn(1, &camDir);
      temp.setPosition(mLight->getPosition() - camDir * (lightRadius + renderPosOffset));
      temp.inverse();
      GFX->setWorldMatrix(temp);
      GFX->setOrtho(-lightRadius, lightRadius, -lightRadius, lightRadius, paraboloidNearPlane, 2.0f * lightRadius, true);
   }
   else
   {
      VectorF camDir;
      MatrixF temp = mLight->getTransform();
      temp.getColumn(1, &camDir);
      temp.setPosition(mLight->getPosition() - camDir * renderPosOffset);
      temp.inverse();
      GFX->setWorldMatrix(temp);

      GFX->setOrtho(-lightRadius, lightRadius, -lightRadius, lightRadius, paraboloidNearPlane, lightRadius, true);
   }

   SceneManager* sceneManager = diffuseState->getSceneManager();
   
   // Front map render
   {
      SceneRenderState frontMapRenderState
      (
         sceneManager,
         SPT_Shadow,
         SceneCameraState::fromGFXWithViewport( diffuseState->getViewport() ),
         renderPass
      );

      frontMapRenderState.getMaterialDelegate().bind( this, &LightShadowMap::getShadowMaterial );
      frontMapRenderState.renderNonLightmappedMeshes( true );
      frontMapRenderState.renderLightmappedMeshes( bUseLightmappedGeometry );
      frontMapRenderState.setDiffuseCameraTransform( diffuseState->getCameraTransform() );
      frontMapRenderState.setWorldToScreenScale( diffuseState->getWorldToScreenScale() );

      if(bUseSinglePassDPM)
      {
         GFX->setWorldMatrix(mWorldToLightProj);
         frontMapRenderState.getRenderPass()->getMatrixSet().setSceneView(mWorldToLightProj);
         GFX->setOrtho(-lightRadius, lightRadius, -lightRadius, lightRadius, paraboloidNearPlane, lightRadius, true);
      }

      GFXDEBUGEVENT_SCOPE( DualParaboloidLightShadowMap_Render_FrontFacingParaboloid, ColorI::RED );
      mShadowMapScale.set(0.5f, 1.0f);
      mShadowMapOffset.set(-0.5f, 0.0f);
      sceneManager->renderSceneNoLights( &frontMapRenderState, SHADOW_TYPEMASK );
      _debugRender( &frontMapRenderState );
   }
   
   // Back map render 
   if(!bUseSinglePassDPM)
   {
      GFXDEBUGEVENT_SCOPE( DualParaboloidLightShadowMap_Render_BackFacingParaboloid, ColorI::RED );

      mShadowMapScale.set(0.5f, 1.0f);
      mShadowMapOffset.set(0.5f, 0.0f);

      // Invert direction on camera matrix
      VectorF right, forward;
      MatrixF temp = mLight->getTransform();
      temp.getColumn( 1, &forward );
      temp.getColumn( 0, &right );
      forward *= -1.0f;      
      right *= -1.0f;
      temp.setColumn( 1, forward );
      temp.setColumn( 0, right );
      temp.setPosition(mLight->getPosition() - forward * -renderPosOffset);
      temp.inverse();
      GFX->setWorldMatrix(temp);

      // Create an inverted scene state for the back-map

      SceneRenderState backMapRenderState
      (
         sceneManager,
         SPT_Shadow,
         SceneCameraState::fromGFXWithViewport( diffuseState->getViewport() ),
         renderPass
      );

      backMapRenderState.getMaterialDelegate().bind( this, &LightShadowMap::getShadowMaterial );
      backMapRenderState.renderNonLightmappedMeshes( true );
      backMapRenderState.renderLightmappedMeshes( bUseLightmappedGeometry );
      backMapRenderState.setDiffuseCameraTransform( diffuseState->getCameraTransform() );
      backMapRenderState.setWorldToScreenScale( diffuseState->getWorldToScreenScale() );

      backMapRenderState.getRenderPass()->getMatrixSet().setSceneView(temp);

      // Draw scene
      sceneManager->renderSceneNoLights( &backMapRenderState );
      _debugRender( &backMapRenderState );
   }

   mTarget->resolve();
   GFX->popActiveRenderTarget();
}