コード例 #1
0
void SceneObject::resetObjectBox()
{
   AssertFatal( mWorldBox.isValidBox(), "SceneObject::resetObjectBox - Bad world box!" );

   mObjBox = mWorldBox;
   mWorldToObj.mul( mObjBox );

   Point3F objScale( mObjScale );
   objScale.setMax( Point3F( (F32)POINT_EPSILON, (F32)POINT_EPSILON, (F32)POINT_EPSILON ) );
   mObjBox.minExtents.convolveInverse( objScale );
   mObjBox.maxExtents.convolveInverse( objScale );

   AssertFatal( mObjBox.isValidBox(), "SceneObject::resetObjectBox - Bad object box!" );

   // Update the mWorldSphere from mWorldBox
   mWorldBox.getCenter( &mWorldSphere.center );
   mWorldSphere.radius = ( mWorldBox.maxExtents - mWorldSphere.center ).len();

   // Update scene managers.
   
   for( SceneObjectLink* link = mSceneObjectLinks; link != NULL; 
        link = link->getNextLink() )
      link->update();
}
コード例 #2
0
void GFXDrawUtil::drawObjectBox( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const MatrixF &objMat, const ColorI &color )
{
   GFXTransformSaver saver;

   mDevice->setStateBlockByDesc( desc );

   MatrixF scaledObjMat( true );
   scaledObjMat = objMat;

   scaledObjMat.scale( size );
   scaledObjMat.setPosition( pos );

   PrimBuild::color( color );
   PrimBuild::begin( GFXLineList, 48 );

   static const Point3F cubePoints[8] = 
   {
      Point3F(-0.5, -0.5, -0.5), Point3F(-0.5, -0.5,  0.5), Point3F(-0.5,  0.5, -0.5), Point3F(-0.5,  0.5,  0.5),
      Point3F( 0.5, -0.5, -0.5), Point3F( 0.5, -0.5,  0.5), Point3F( 0.5,  0.5, -0.5), Point3F( 0.5,  0.5,  0.5)
   };

   // 8 corner points of the box   
   for ( U32 i = 0; i < 8; i++ )
   {
      //const Point3F &start = cubePoints[i];  

      // 3 lines per corner point
      for ( U32 j = 0; j < 3; j++ )
      {
         Point3F start = cubePoints[i];
         Point3F end = start;
         end[j] *= 0.8f;

         scaledObjMat.mulP(start);
         PrimBuild::vertex3fv(start);
         scaledObjMat.mulP(end);
         PrimBuild::vertex3fv(end);            
      }
   }

   PrimBuild::end();
}
コード例 #3
0
bool afxEA_ZodiacPlane::ea_start()
{
  if (!zode_data)
  {
    Con::errorf("afxEA_ZodiacPlane::ea_start() -- missing or incompatible datablock.");
    return false;
  }

  do_runtime_substitutions();

  if (!zode_data->use_full_xfm)
    zode_angle_offset = calc_facing_angle();

  switch (zode_data->face_dir)
  {
  case afxZodiacPlaneData::FACES_UP:
    aa_rot.set(Point3F(0.0f,0.0f,1.0f),0.0f);
    break;  
  case afxZodiacPlaneData::FACES_DOWN:
    aa_rot.set(Point3F(0.0f,0.0f,-1.0f),0.0f);
    break;  
  case afxZodiacPlaneData::FACES_FORWARD:
    aa_rot.set(Point3F(0.0f,1.0f,0.0f),0.0f);
    break;  
  case afxZodiacPlaneData::FACES_BACK:
    aa_rot.set(Point3F(0.0f,-1.0f,0.0f),0.0f);
    break;  
  case afxZodiacPlaneData::FACES_RIGHT:
    aa_rot.set(Point3F(1.0f,0.0f,0.0f),0.0f);
    break;  
  case afxZodiacPlaneData::FACES_LEFT:
    aa_rot.set(Point3F(-1.0f,0.0f,0.0f),0.0f);
    break;  
  }

  return true;
}
コード例 #4
0
ファイル: mPolyhedronTest.cpp プロジェクト: 03050903/Torque3D
 virtual void SetUp()
 {
    // Build planes for a unit cube centered at the origin.
    // Note that the normals must be facing inwards.
    planes.push_back(PlaneF(Point3F(-0.5f,  0.f,   0.f ), Point3F( 1.f,  0.f,  0.f)));
    planes.push_back(PlaneF(Point3F( 0.5f,  0.f,   0.f ), Point3F(-1.f,  0.f,  0.f)));
    planes.push_back(PlaneF(Point3F( 0.f,  -0.5f,  0.f ), Point3F( 0.f,  1.f,  0.f)));
    planes.push_back(PlaneF(Point3F( 0.f,   0.5f,  0.f ), Point3F( 0.f, -1.f,  0.f)));
    planes.push_back(PlaneF(Point3F( 0.f,   0.f,  -0.5f), Point3F( 0.f,  0.f,  1.f)));
    planes.push_back(PlaneF(Point3F( 0.f,   0.f,   0.5f), Point3F( 0.f,  0.f, -1.f)));
 }
コード例 #5
0
#include <stdio.h>
#include "platform/platform.h"
#include "T3D/Trigger.h"
#include "T3D/aiFishPlayer.h"
#include "T3D/InfluenceWander.h"

const static F32  BOUNDARY_SIZE = 0.2f;   //when fish get this near boundary, the try and turn back
const static F32  BOUNCE_ANGLE = 0.5f;    //when cross boundary, this is the angle they turn in by (radians)

const static F32  TAN_BOUNCE_ANGLE = tanf(BOUNCE_ANGLE);
const static Point3F BOUNDARY_VECTOR = Point3F(BOUNDARY_SIZE,BOUNDARY_SIZE,BOUNDARY_SIZE);

bool  InfluenceWander::update()
{
   if( !Parent::update() ){
      return false;
   }
   //---choose new direction ever so often----------------------
   if(mTimeOut<getTimeSeconds()){
      onExpired();
   }
   return true;
}
void           InfluenceWander::onExpired()
{
#ifdef   DEBUG_HUD
//   mFish->addLog("wander expired");
#endif
   Point3F  wanderDirection = mFish->getHeading();
   reset( &wanderDirection );
}
コード例 #6
0
void Frustum::setProjectionOffset(const Point2F& offsetMat)
{
   mProjectionOffset = offsetMat;
   mProjectionOffsetMatrix.identity();
   mProjectionOffsetMatrix.setPosition(Point3F(mProjectionOffset.x, mProjectionOffset.y, 0.0f));
}
コード例 #7
0
ファイル: gameTSCtrl.cpp プロジェクト: adhistac/ee-client-2-0
//-----------------------------------------------------------------------------
// Torque 3D
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

#include "T3D/gameTSCtrl.h"
#include "console/consoleTypes.h"
#include "T3D/gameBase.h"
#include "T3D/gameConnection.h"
#include "T3D/shapeBase.h"
#include "T3D/gameFunctions.h"

//---------------------------------------------------------------------------
// Debug stuff:
Point3F lineTestStart = Point3F(0, 0, 0);
Point3F lineTestEnd =   Point3F(0, 1000, 0);
Point3F lineTestIntersect =  Point3F(0, 0, 0);
bool gSnapLine = false;

//----------------------------------------------------------------------------
// Class: GameTSCtrl
//----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(GameTSCtrl);

GameTSCtrl::GameTSCtrl()
{
}

//---------------------------------------------------------------------------
bool GameTSCtrl::onAdd()
{
コード例 #8
0
bool AtlasGeomChunkTracer::castLeafRay(const Point2I pos, const Point3F &start,
                                       const Point3F &end, const F32 &startT, 
                                       const F32 &endT, RayInfo *info)
{
   if(AtlasInstance::smRayCollisionDebugLevel == AtlasInstance::RayCollisionDebugToColTree)
   {
      const F32 invSize = 1.f / F32(BIT(mTreeDepth-1));

      // This is a bit of a hack. But good for testing.
      // Do collision against the collision tree leaf bounding box and return the result...
      F32 t; Point3F n;
      Box3F box;

      box.minExtents.set(Point3F(F32(pos.x  ) * invSize, F32(pos.y  ) * invSize, getSquareMin(0, pos)));
      box.maxExtents.set(Point3F(F32(pos.x+1) * invSize, F32(pos.y+1) * invSize, getSquareMax(0, pos)));

      //Con::printf("   checking at xy = {%f, %f}->{%f, %f}, [%d, %d]", start.x, start.y, end.x, end.y, pos.x, pos.y);

      if(box.collideLine(start, end, &t, &n) && t >= startT && t <= endT)
      {
         info->t      = t;
         info->normal = n;
         return true;
      }

      return false;
   }
   else if( AtlasInstance::smRayCollisionDebugLevel == AtlasInstance::RayCollisionDebugToMesh )
   {
	   bool haveHit = false;
	   U32 currentIdx = 0;
	   U32 numIdx = mChunk->mIndexCount;
	   F32 bestT = F32_MAX;
	   U32 bestTri = -1;
	   Point2F bestBary;

	   while( !haveHit && currentIdx < numIdx )
	   {
		   const Point3F& a = mChunk->mVert[ mChunk->mIndex[ currentIdx ] ].point;
		   const Point3F& b = mChunk->mVert[ mChunk->mIndex[ currentIdx + 1 ] ].point;
		   const Point3F& c = mChunk->mVert[ mChunk->mIndex[ currentIdx + 2 ] ].point;

		   F32     localT;
		   Point2F localBary;

		   // Do the cast, using our conveniently precalculated ray delta...
		   if(castRayTriangle(mRayStart, mRayDelta, a,b,c, localT, localBary))
		   {
			   if(localT < bestT)
			   {
				   // And it hit before anything else we've seen.
				   bestTri  = currentIdx;
				   bestT    = localT;
				   bestBary = localBary;

				   haveHit = true;
			   }
		   }

		   currentIdx += 3;
	   }

      // Fill in extra info for the hit.
      if(!haveHit)
         return false;

      // Calculate the normal, we skip that for the initial check.
      Point3F norm; // Hi norm!

      const Point3F &a = mChunk->mVert[mChunk->mIndex[bestTri+0]].point;
      const Point3F &b = mChunk->mVert[mChunk->mIndex[bestTri+1]].point;
      const Point3F &c = mChunk->mVert[mChunk->mIndex[bestTri+2]].point;

      const Point2F &aTC = mChunk->mVert[mChunk->mIndex[bestTri+0]].texCoord;
      const Point2F &bTC = mChunk->mVert[mChunk->mIndex[bestTri+1]].texCoord;
      const Point2F &cTC = mChunk->mVert[mChunk->mIndex[bestTri+2]].texCoord;

      // Store everything relevant into the info structure.
      info->t = bestT;

      const Point3F e0 = b-a;
      const Point3F e1 = c-a;

      info->normal = mCross(e1, e0);
      info->normal.normalize();

      // Calculate and store the texture coords.
      const Point2F e0TC = bTC-aTC;
      const Point2F e1TC = cTC-aTC;
      info->texCoord = e0TC * bestBary.x + e1TC * bestBary.y + aTC;

      // Return true, we hit something!
      return true;
   }
   else
   {
      // Get the triangle list...
      U16 *triOffset = mChunk->mColIndicesBuffer + 
         mChunk->mColIndicesOffsets[pos.x * BIT(mChunk->mColTreeDepth-1) + pos.y];

      // Store best hit results...
      bool gotHit = false;
      F32 bestT = F32_MAX;
      U16 bestTri = -1, offset;
      Point2F bestBary;

      while((offset = *triOffset) != 0xFFFF)
      {
         // Advance to the next triangle..
         triOffset++;

         // Get each triangle, and do a raycast against it.
         Point3F a,b,c;

         AssertFatal(offset <  mChunk->mIndexCount, 
            "AtlasGeomTracer2::castLeafRay - offset past end of index list.");

         a = mChunk->mVert[mChunk->mIndex[offset+0]].point;
         b = mChunk->mVert[mChunk->mIndex[offset+1]].point;
         c = mChunk->mVert[mChunk->mIndex[offset+2]].point;

         /*Con::printf("  o testing triangle %d ({%f,%f,%f},{%f,%f,%f},{%f,%f,%f})",
                              offset, a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z); */

         F32     localT;
         Point2F localBary;

         // Do the cast, using our conveniently precalculated ray delta...
         if(castRayTriangle(mRayStart, mRayDelta, a,b,c, localT, localBary))
         {
            //Con::printf(" - hit triangle %d at  t=%f", offset, localT);

            // The ray intersected, but we have to make sure we hit actually on
            // the line segment. (ie, a ray isn't a ray, Ray.)

            // BJGTODO - This should prevent some nasty edge cases, but we
            //           seem to be calculating the wrong start and end T's.
            //           So I've disabled this for now but it will cause
            //           problems later!
            //if(localT < startT || localT > endT)
            //   continue;

            // It really, really hit, wow!
            if(localT < bestT)
            {
               // And it hit before anything else we've seen.
               bestTri  = offset;
               bestT    = localT;
               bestBary = localBary;

               gotHit = true;
            }
         }
         else
         {
            //Con::printf(" - didn't hit triangle %d at  t=%f", offset, localT);
         }
      }

      // Fill in extra info for the hit.
      if(!gotHit)
         return false;

      // Calculate the normal, we skip that for the initial check.
      Point3F norm; // Hi norm!

      const Point3F &a = mChunk->mVert[mChunk->mIndex[bestTri+0]].point;
      const Point3F &b = mChunk->mVert[mChunk->mIndex[bestTri+1]].point;
      const Point3F &c = mChunk->mVert[mChunk->mIndex[bestTri+2]].point;

      const Point2F &aTC = mChunk->mVert[mChunk->mIndex[bestTri+0]].texCoord;
      const Point2F &bTC = mChunk->mVert[mChunk->mIndex[bestTri+1]].texCoord;
      const Point2F &cTC = mChunk->mVert[mChunk->mIndex[bestTri+2]].texCoord;

      // Store everything relevant into the info structure.
      info->t = bestT;

      const Point3F e0 = b-a;
      const Point3F e1 = c-a;

      info->normal = mCross(e1, e0);
      info->normal.normalize();

      // Calculate and store the texture coords.
      const Point2F e0TC = bTC-aTC;
      const Point2F e1TC = cTC-aTC;
      info->texCoord = e0TC * bestBary.x + e1TC * bestBary.y + aTC;

      // Return true, we hit something!
      return true;
   }
}
コード例 #9
0
/**
 * Clears the aim location and sets it to the bot's
 * current destination so he looks where he's going
 */
void AIPlayer::clearAim()
{
   mAimObject = 0;
   mAimLocationSet = false;
   mAimOffset = Point3F(0.0f, 0.0f, 0.0f);
}
コード例 #10
0
ファイル: aiPlayer.cpp プロジェクト: elfprince13/Torque3D
/**
 * This method calculates the moves for the AI player
 *
 * @param movePtr Pointer to move the move list into
 */
bool AIPlayer::getAIMove(Move *movePtr)
{
   *movePtr = NullMove;

   // Use the eye as the current position.
   MatrixF eye;
   getEyeTransform(&eye);
   Point3F location = eye.getPosition();
   Point3F rotation = getRotation();

#ifdef TORQUE_NAVIGATION_ENABLED
   if(mDamageState == Enabled)
   {
      if(mMoveState != ModeStop)
         updateNavMesh();
      if(!mFollowData.object.isNull())
      {
         if(mPathData.path.isNull())
         {
            if((getPosition() - mFollowData.object->getPosition()).len() > mFollowData.radius)
               followObject(mFollowData.object, mFollowData.radius);
         }
         else
         {
            if((mPathData.path->mTo - mFollowData.object->getPosition()).len() > mFollowData.radius)
               repath();
            else if((getPosition() - mFollowData.object->getPosition()).len() < mFollowData.radius)
            {
               clearPath();
               mMoveState = ModeStop;
            throwCallback("onTargetInRange");
            }
            else if((getPosition() - mFollowData.object->getPosition()).len() < mAttackRadius)
            {
            throwCallback("onTargetInFiringRange");
            }
         }
      }
   }
#endif // TORQUE_NAVIGATION_ENABLED

   // Orient towards the aim point, aim object, or towards
   // our destination.
   if (mAimObject || mAimLocationSet || mMoveState != ModeStop) 
   {
      // Update the aim position if we're aiming for an object
      if (mAimObject)
         mAimLocation = mAimObject->getPosition() + mAimOffset;
      else
         if (!mAimLocationSet)
            mAimLocation = mMoveDestination;

      F32 xDiff = mAimLocation.x - location.x;
      F32 yDiff = mAimLocation.y - location.y;

      if (!mIsZero(xDiff) || !mIsZero(yDiff)) 
      {
         // First do Yaw
         // use the cur yaw between -Pi and Pi
         F32 curYaw = rotation.z;
         while (curYaw > M_2PI_F)
            curYaw -= M_2PI_F;
         while (curYaw < -M_2PI_F)
            curYaw += M_2PI_F;

         // find the yaw offset
         F32 newYaw = mAtan2( xDiff, yDiff );
         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_PI_F )
            yawDiff -= M_2PI_F;
         else if( yawDiff < -M_PI_F )
            yawDiff += M_2PI_F;

         movePtr->yaw = yawDiff;

         // Next do pitch.
         if (!mAimObject && !mAimLocationSet) 
         {
            // Level out if were just looking at our next way point.
            Point3F headRotation = getHeadRotation();
            movePtr->pitch = -headRotation.x;
         }
         else 
         {
            // This should be adjusted to run from the
            // eye point to the object's center position. Though this
            // works well enough for now.
            F32 vertDist = mAimLocation.z - location.z;
            F32 horzDist = mSqrt(xDiff * xDiff + yDiff * yDiff);
            F32 newPitch = mAtan2( horzDist, vertDist ) - ( M_PI_F / 2.0f );
            if (mFabs(newPitch) > 0.01f) 
            {
               Point3F headRotation = getHeadRotation();
               movePtr->pitch = newPitch - headRotation.x;
            }
         }
      }
   }
   else 
   {
      // Level out if we're not doing anything else
      Point3F headRotation = getHeadRotation();
      movePtr->pitch = -headRotation.x;
   }

   // Move towards the destination
   if (mMoveState != ModeStop) 
   {
      F32 xDiff = mMoveDestination.x - location.x;
      F32 yDiff = mMoveDestination.y - location.y;

      // Check if we should mMove, or if we are 'close enough'
      if (mFabs(xDiff) < mMoveTolerance && mFabs(yDiff) < mMoveTolerance) 
      {
         mMoveState = ModeStop;
         onReachDestination();
      }
      else 
      {
         // Build move direction in world space
         if (mIsZero(xDiff))
            movePtr->y = (location.y > mMoveDestination.y) ? -1.0f : 1.0f;
         else
            if (mIsZero(yDiff))
               movePtr->x = (location.x > mMoveDestination.x) ? -1.0f : 1.0f;
            else
               if (mFabs(xDiff) > mFabs(yDiff)) 
               {
                  F32 value = mFabs(yDiff / xDiff);
                  movePtr->y = (location.y > mMoveDestination.y) ? -value : value;
                  movePtr->x = (location.x > mMoveDestination.x) ? -1.0f : 1.0f;
               }
               else 
               {
                  F32 value = mFabs(xDiff / yDiff);
                  movePtr->x = (location.x > mMoveDestination.x) ? -value : value;
                  movePtr->y = (location.y > mMoveDestination.y) ? -1.0f : 1.0f;
               }

         // Rotate the move into object space (this really only needs
         // a 2D matrix)
         Point3F newMove;
         MatrixF moveMatrix;
         moveMatrix.set(EulerF(0.0f, 0.0f, -(rotation.z + movePtr->yaw)));
         moveMatrix.mulV( Point3F( movePtr->x, movePtr->y, 0.0f ), &newMove );
         movePtr->x = newMove.x;
         movePtr->y = newMove.y;

         // Set movement speed.  We'll slow down once we get close
         // to try and stop on the spot...
         if (mMoveSlowdown) 
         {
            F32 speed = mMoveSpeed;
            F32 dist = mSqrt(xDiff*xDiff + yDiff*yDiff);
            F32 maxDist = mMoveTolerance*2;
            if (dist < maxDist)
               speed *= dist / maxDist;
            movePtr->x *= speed;
            movePtr->y *= speed;

            mMoveState = ModeSlowing;
         }
         else 
         {
            movePtr->x *= mMoveSpeed;
            movePtr->y *= mMoveSpeed;

            mMoveState = ModeMove;
         }

         if (mMoveStuckTestCountdown > 0)
            --mMoveStuckTestCountdown;
         else
         {
            // We should check to see if we are stuck...
            F32 locationDelta = (location - mLastLocation).len();
            if (locationDelta < mMoveStuckTolerance && mDamageState == Enabled) 
            {
               // If we are slowing down, then it's likely that our location delta will be less than
               // our move stuck tolerance. Because we can be both slowing and stuck
               // we should TRY to check if we've moved. This could use better detection.
               if ( mMoveState != ModeSlowing || locationDelta == 0 )
               {
                  mMoveState = ModeStuck;
                  onStuck();
               }
            }
         }
      }
   }

   // Test for target location in sight if it's an object. The LOS is
   // run from the eye position to the center of the object's bounding,
   // which is not very accurate.
   if (mAimObject)
   {
      if (checkInLos(mAimObject.getPointer()))
      {
         if (!mTargetInLOS)
         {
            throwCallback( "onTargetEnterLOS" );
            mTargetInLOS = true;
         }
   }
      else if (mTargetInLOS)
      {
            throwCallback( "onTargetExitLOS" );
            mTargetInLOS = false;
         }
      }

   Pose desiredPose = mPose;

   if ( mSwimming )  
      desiredPose = SwimPose;   
   else if ( mAiPose == 1 && canCrouch() )   
      desiredPose = CrouchPose;  
   else if ( mAiPose == 2 && canProne() )  
      desiredPose = PronePose;  
   else if ( mAiPose == 3 && canSprint() )  
      desiredPose = SprintPose;  
   else if ( canStand() )  
      desiredPose = StandPose;  
  
   setPose( desiredPose );
   
   // Replicate the trigger state into the move so that
   // triggers can be controlled from scripts.
   for( U32 i = 0; i < MaxTriggerKeys; i++ )
      movePtr->trigger[ i ] = getImageTriggerState( i );

#ifdef TORQUE_NAVIGATION_ENABLED
   if(mJump == Now)
   {
      movePtr->trigger[2] = true;
      mJump = None;
   }
   else if(mJump == Ledge)
   {
      // If we're not touching the ground, jump!
      RayInfo info;
      if(!getContainer()->castRay(getPosition(), getPosition() - Point3F(0, 0, 0.4f), StaticShapeObjectType, &info))
      {
         movePtr->trigger[2] = true;
         mJump = None;
      }
   }
#endif // TORQUE_NAVIGATION_ENABLED

   mLastLocation = location;

   return true;
}
コード例 #11
0
void PlanetRenderImage::render(TSRenderContext &rc)
{
   // A simple planet culling scheme would be to dot the line of sight
   // with the vector from the camera to the planet.  This would eliminate
   // the length test of v below (after m_cross((Point3F)plane, vpNormal, &v))
   GFXSurface *gfxSurface = rc.getSurface();

   gfxSurface->setHazeSource(GFX_HAZE_NONE);
   gfxSurface->setShadeSource(GFX_SHADE_CONSTANT);
   gfxSurface->setAlphaSource(GFX_ALPHA_NONE);
	gfxSurface->setFillMode(GFX_FILL_TEXTURE);
	gfxSurface->setTransparency(FALSE);
   gfxSurface->setTexturePerspective(FALSE);

   gfxSurface->setConstantShade(1.0f);

   int textureHeight;
   gfxSurface->setTextureMap(texture);
   textureHeight = texture->height;
   
   TSCamera *camera = rc.getCamera();
  
   TS::PointArray *pointArray = rc.getPointArray();
   pointArray->reset();
   pointArray->useIntensities(false);
   pointArray->useTextures(textCoord);
   pointArray->useTextures(true);
	pointArray->setVisibility( TS::ClipMask );

   // find out how high the bitmap is at 100% as projected onto the viewport,
   // texel:pixel will be 1:1 at 640x480
   //const RectF &worldVP  = camera->getWorldViewport();
   //const float h = textureHeight*((worldVP.upperL.y - worldVP.lowerR.y)/480.0f);
   //const float sz = 0.5*distance*(h/camera->getNearDist());

   // find the position of the planet
   Point3F displacement = camera->getTCW().p;
   //displacement.z *= -(distance - visibleDistance)/visibleDistance;
   displacement.z = -displacement.z*(distance/(visibleDistance*1.5f));
   Point3F pos = position;
   pos += displacement;
 
   // find the normal to the view plane in world coords
   Point3F v0(0.0f, 1.0f, 0.0f), vpNormal;
   m_mul(v0, (RMat3F)camera->getTCW(), &vpNormal);
   vpNormal.normalize();

   // construct the plane that the camera, planet pos & celestial NP all
   // lie on
   PlaneF plane(pos, camera->getTCW().p, 
      Point3F(displacement.x, displacement.y, displacement.z + distance));

   // the cross product of the VP normal and the normal to the plane just
   // constructed is the up vector for the planet
   Point3F v;
   m_cross((Point3F)plane, vpNormal, &v);
   if (IsEqual(v.len(), 0.0f))
      // planet is directly to the right or left of camera
      return;
   v.normalize();
   
   // cross the up with the normal and we get the right vector
   Point3F u;
   m_cross(vpNormal, v, &u);
   u *= size;
   v *= size;

   TS::VertexIndexPair V[6];
   Point3F ul = pos;
   ul -= u; ul += v;
   V[0].fVertexIndex   = pointArray->addPoint(ul);
   V[0].fTextureIndex  = 0;
   Point3F ur = pos;
   ur += u; ur += v;
   V[1].fVertexIndex   = pointArray->addPoint(ur);
   V[1].fTextureIndex  = 1;
   Point3F lr = pos;
   lr += u; lr -= v;
   V[2].fVertexIndex   = pointArray->addPoint(lr);
   V[2].fTextureIndex  = 2;
   Point3F ll = pos;
   ll -= u; ll -=v;
   V[3].fVertexIndex   = pointArray->addPoint(ll);
   V[3].fTextureIndex  = 3;
	if (gfxSurface->getCaps() & GFX_DEVCAP_SUPPORTS_CONST_ALPHA)
	   gfxSurface->setZTest(GFX_NO_ZTEST);
   pointArray->drawPoly(4, V, 0);
	if (gfxSurface->getCaps() & GFX_DEVCAP_SUPPORTS_CONST_ALPHA)
	   gfxSurface->setZTest(GFX_ZTEST_AND_WRITE);
   if(lensFlare) {
      TS::TransformedVertex vx;
      camera->transformProject(pos, &vx);
      bool vis = vx.fStatus & TS::TransformedVertex::Projected;
      lensFlare->setSunPos(vis, vx.fPoint, pos);
   }
}
コード例 #12
0
void SimPlanet::load()
{
   unload();
   
   if ((textureTag != 0) && (!manager->isServer())) {
      ResourceManager &rm = *SimResource::get(manager);
      const char *filename = SimTagDictionary::getString(manager, textureTag);
   
      // load the texture
      hTexture = rm.load(filename);
      AssertWarn((bool)hTexture, 
         avar("Error reading bitmap file \"%s\"", filename));
      // don't want to assert fatal because we don't want to bring down
      // the mission editor
      if ((bool)hTexture) {
         planet.texture = (GFXBitmap *)hTexture;
         addToSet(SimRenderSetId);
         inRenderSet = true;
      }         
   }   
   else
      planet.texture = NULL;

   // calculate planet position in world coordinates
   // add 90 to azimuth so that zero is at up Y axis
   if (incidence > 89.0f)
      incidence = 89.0f;
   if (incidence < -89.0f)
      incidence = -89.0f;
   const float az = azimuth + 90.0f;
   const float c = planet.distance*m_cos(DEGRAD*incidence);
   planet.position = Point3F(c*m_cos(DEGRAD*az), c*m_sin(DEGRAD*az), planet.distance*m_sin(DEGRAD*incidence));

   // initialize light if any
   Point3F direction = planet.position;
   direction.normalize();
   direction *= -1.0f;

   if (castShadows) {
      // set static data items
      shadowDirection = direction;
      shadows = true;
   }


   light.setAim(direction);
   //light.setType(TS::Light::LightDirectional);
   light.setType(TS::Light::LightDirectionalWrap);
   light.setIntensity(intensity.red, intensity.green, intensity.blue);
   if (intensity.red > 0.0f || intensity.green > 0.0f || intensity.blue > 0.0f 
      || ambient.red > 0.0f || ambient.green > 0.0f || ambient.blue > 0.0f) {
      addToSet(SimLightSetId);
      inLightSet = true;
      lensFlare.setColor(intensity);
   }
   planet.lensFlare = useLensFlare ? &lensFlare : NULL;

   // initialize static texture coordinates
   textCoord[0].x = 0.0f;  textCoord[0].y = 0.0f;
   textCoord[1].x = 1.0f;  textCoord[1].y = 0.0f;
   textCoord[2].x = 1.0f;  textCoord[2].y = 1.0f;
   textCoord[3].x = 0.0f;  textCoord[3].y = 1.0f;

   setMaskBits(Modified);
}
コード例 #13
0
void LensFlare::render(TSRenderContext &rc)
{
   if (!renderDetail) {
      renderCount = 0;
      return;
   }

   GFXSurface *gfxSurface = rc.getSurface();
   if(!visible || !flares.size() || !(gfxSurface->getCaps() & GFX_DEVCAP_SUPPORTS_CONST_ALPHA)) {
      renderCount = 0;
      return;
   }

   renderCount++;
   if (obscured && renderCount%15 != 1)
      // if something was in the way last time we checked LOS, and it isn't time
      // to check LOS again, bail out early
      return;

   TS::PointArray *pointArray = rc.getPointArray();
   pointArray->reset();
   pointArray->useIntensities(false);
   pointArray->useTextures(textCoord);
   pointArray->useTextures(true);
	pointArray->setVisibility( TS::ClipMask );
   pointArray->useHazes(false);

   gfxSurface->setHazeSource(GFX_HAZE_NONE);
   gfxSurface->setShadeSource(GFX_SHADE_NONE);
	gfxSurface->setTransparency(FALSE);
   gfxSurface->setTexturePerspective(FALSE);
	gfxSurface->setFillMode(GFX_FILL_TEXTURE);
   gfxSurface->setTransparency(TRUE);
   gfxSurface->setAlphaSource(GFX_ALPHA_TEXTURE);

   TS::VertexIndexPair V[4];
   // if it was in the screen, go ahead and draw the lens flare.
   TSCamera *camera = rc.getCamera();
   RectI const &screenVp = camera->getScreenViewport();
   const Point2F vpSize(screenVp.lowerR.x - screenVp.upperL.x, screenVp.upperL.y + screenVp.lowerR.y);
   // preserve relative size of the textures, they should be
   // 1:1 on a 640x480 viewport
   Point2F vpScale(vpSize.x/640.0f, vpSize.y/480.0f);
   float scrSize = min(vpSize.x, vpSize.y);
   Point2F sunP(sunPosProjected.x, sunPosProjected.y);
   Point2F delta((screenVp.upperL.x + screenVp.lowerR.x) >> 1, (screenVp.upperL.y + screenVp.lowerR.y) >> 1);
   
   // find vector of the flare
   delta -= sunP;
   float deltaLen = delta.len();
   float deltaFrac = 2.0f*deltaLen / scrSize;
   float constAlpha = .5f*(1.0f - deltaFrac);
   if (constAlpha <= 0.0f)
   {
		if (renderCount == 1)
			renderCount = 0;
      return;
	}

   if (root && renderCount%15 == 1) {
      // do a LOS query, see if anything is in the way
      SimCollisionInfo collision;
      SimContainerQuery query;
      query.id    = 0;
      query.type  = SimContainerQuery::DefaultDetail;
      query.mask  = -1;
      Vector3F v = sunPosWorld - camera->getTCW().p;
      v.normalizef();
      v *= 2.0f;
      query.box.fMin = camera->getTCW().p + v;
      query.box.fMax = sunPosWorld;
      if (root->findLOS(query, &collision, SimCollisionImageQuery::High)) {
         obscured = true;
         return;
      }
   }
   obscured = false;
   gfxSurface->setConstantAlpha(constAlpha);
   
   // generate rotated box info
   float angle;
   if (delta.x == 0.0f && delta.y == 0.0f)
      angle = 0.0f;
   else
      angle = m_atan(delta.x, delta.y) - M_PI/2.0f;
   float c = m_cos(angle), s = m_sin(angle);
   float a = c*(-1.0f) - s*(-1.0f), b = s*(-1.0f) + c*(-1.0f);
   Point2F rotPoints[4];
   rotPoints[0].x =  a;  rotPoints[0].y =  b;
   rotPoints[1].x = -b;  rotPoints[1].y =  a;
   rotPoints[2].x = -a;  rotPoints[2].y = -b;
   rotPoints[3].x =  b;  rotPoints[3].y = -a;

   for (int i = 0; i < flares.size(); i++) {
      const FlareInfo &flare = flares[i];
      Point2F flarePos = delta;
      flarePos *= flare.dist;
      flarePos += sunP;
      const GFXBitmap *bitmap = hMaterialList->getMaterial(flare.textureIndex).getTextureMap();
      gfxSurface->setTextureMap(bitmap);
      Point2F dimension(bitmap->width*vpScale.x, bitmap->height*vpScale.y);
      const float scale = 0.5*(flare.minScale + (1.0f - deltaFrac)*flare.scaleRange);
      for (int j = 0; j < 4; j++) {
         Point3F drawPoint;
         if (flare.rotate)
            drawPoint.set(rotPoints[j].x*dimension.x, rotPoints[j].y*dimension.y, 0);
         else
            drawPoint.set(boxPoints[j][0]*dimension.x, boxPoints[j][1]*dimension.y, 0);
         drawPoint *= scale;
         drawPoint += Point3F(flarePos.x, flarePos.y, 1.0);
         V[j].fVertexIndex = pointArray->addProjectedPoint(drawPoint);
         V[j].fTextureIndex = j;
      }
      pointArray->drawProjectedPoly(4, V, 0);
   }
   
   gfxSurface->setTransparency(FALSE);
   if(deltaFrac < .3)
   {
      pointArray->useTextures(false);
      gfxSurface->setAlphaSource(GFX_ALPHA_CONSTANT);
      gfxSurface->setFillMode(GFX_FILL_CONSTANT);
      gfxSurface->setConstantAlpha(3.3 * (.3 - deltaFrac));
      gfxSurface->setFillColor(&color);
      V[0].fVertexIndex = pointArray->addProjectedPoint(Point3F(screenVp.upperL.x, screenVp.upperL.y, 1.0));
      V[1].fVertexIndex = pointArray->addProjectedPoint(Point3F(screenVp.lowerR.x, screenVp.upperL.y, 1.0));
      V[2].fVertexIndex = pointArray->addProjectedPoint(Point3F(screenVp.lowerR.x, screenVp.lowerR.y, 1.0));
      V[3].fVertexIndex = pointArray->addProjectedPoint(Point3F(screenVp.upperL.x, screenVp.lowerR.y, 1.0));
      pointArray->drawProjectedPoly(4, V, 0);
   }

   gfxSurface->setAlphaSource(GFX_ALPHA_NONE);
}
コード例 #14
0
      V[0].fVertexIndex = pointArray->addProjectedPoint(Point3F(screenVp.upperL.x, screenVp.upperL.y, 1.0));
      V[1].fVertexIndex = pointArray->addProjectedPoint(Point3F(screenVp.lowerR.x, screenVp.upperL.y, 1.0));
      V[2].fVertexIndex = pointArray->addProjectedPoint(Point3F(screenVp.lowerR.x, screenVp.lowerR.y, 1.0));
      V[3].fVertexIndex = pointArray->addProjectedPoint(Point3F(screenVp.upperL.x, screenVp.lowerR.y, 1.0));
      pointArray->drawProjectedPoly(4, V, 0);
   }

   gfxSurface->setAlphaSource(GFX_ALPHA_NONE);
}

//--------------------------------------------------------------------------- 

//--------------------------------------------------------------------------- 

bool SimPlanet::shadows = false;
Point3F SimPlanet::shadowDirection = Point3F(0.0f, 0.0f, 1.0f);

SimPlanet::SimPlanet()
{ 
   planet.itype = SimRenderImage::Background;
   planet.sortValue = PLANET_SORTVALUE;
   planet.lensFlare = NULL;
   planet.size = 2000.0f;
   planet.distance = PLANET_DISTANCE;
   textureTag = 0;
   azimuth = 0.0f;
   incidence = 30.0f;
   castShadows = false;
   useLensFlare = false;
   inLightSet = false;
   inRenderSet = false;
コード例 #15
0
Box3F ForestConvex::getBoundingBox() const
{
   // This is probably a bad idea? -- BJG
   return getBoundingBox( mTransform, Point3F(mScale,mScale,mScale) );
}
コード例 #16
0
ファイル: lightFlareData.cpp プロジェクト: AlkexGas/Torque3D
void LightFlareData::prepRender( SceneRenderState *state, LightFlareState *flareState )
{
   PROFILE_SCOPE( LightFlareData_prepRender );

   const LightInfo *lightInfo = flareState->lightInfo;

   if (  mIsZero( flareState->fullBrightness ) ||
         mIsZero( lightInfo->getBrightness() ) )
      return;

   // Figure out the element count to render.
   U32 elementCount = mElementCount;
   const bool isReflectPass = state->isReflectPass();
   if ( isReflectPass )
   {
      // Then we don't render anything this pass.
      if ( !mRenderReflectPass )
         return;

      // Find the zero distance elements which make 
      // up the corona of the light flare.
      elementCount = 0.0f;
      for ( U32 i=0; i < mElementCount; i++ )
         if ( mIsZero( mElementDist[i] ) )
            elementCount++;
   }

   // Better have something to render.
   if ( elementCount == 0 )
      return;
  
   U32 visDelta = U32_MAX;
   F32 occlusionFade = 1.0f;
   Point3F lightPosSS;
   bool lightVisible = _testVisibility( state, flareState, &visDelta, &occlusionFade, &lightPosSS );
   
   // We can only skip rendering if the light is not 
   // visible, and it has elapsed the fade out time.
   if (  mIsZero( occlusionFade ) ||
         !lightVisible && visDelta > FadeOutTime )
      return;

   const RectI &viewport = GFX->getViewport();
   Point3F oneOverViewportExtent( 1.0f / (F32)viewport.extent.x, 1.0f / (F32)viewport.extent.y, 0.0f );

   // Really convert it to screen space.
   lightPosSS.x -= viewport.point.x;
   lightPosSS.y -= viewport.point.y;
   lightPosSS *= oneOverViewportExtent;
   lightPosSS = ( lightPosSS * 2.0f ) - Point3F::One;
   lightPosSS.y = -lightPosSS.y;
   lightPosSS.z = 0.0f;

   // Take any projection offset into account so that the point where the flare's
   // elements converge is at the 'eye' point rather than the center of the viewport.
   const Point2F& projOffset = state->getCameraFrustum().getProjectionOffset();
   Point3F flareVec( -lightPosSS + Point3F(projOffset.x, projOffset.y, 0.0f) );
   const F32 flareLength = flareVec.len();
   if ( flareLength > 0.0f )
      flareVec *= 1.0f / flareLength;

   // Setup the flare quad points.
   Point3F rotatedBasePoints[4];
   dMemcpy(rotatedBasePoints, sBasePoints, sizeof( sBasePoints ));

   // Rotate the flare quad.
   F32 rot = mAcos( -1.0f * flareVec.x );
   rot *= flareVec.y > 0.0f ? -1.0f : 1.0f;
   MathUtils::vectorRotateZAxis( rot, rotatedBasePoints, 4 );

   // Here we calculate a the light source's influence on 
   // the effect's size and brightness.

   // Scale based on the current light brightness compared to its normal output.
   F32 lightSourceBrightnessScale = lightInfo->getBrightness() / flareState->fullBrightness;

   const Point3F &camPos = state->getCameraPosition();
   const Point3F &lightPos = flareState->lightMat.getPosition();   
   const bool isVectorLight = lightInfo->getType() == LightInfo::Vector;

   // Scale based on world space distance from camera to light source.
   F32 distToCamera = ( camPos - lightPos ).len();
   F32 lightSourceWSDistanceScale = isVectorLight && distToCamera > 0.0f ? 1.0f : getMin( 10.0f / distToCamera, 10.0f );

   // Scale based on screen space distance from screen position of light source to the screen center.
   F32 lightSourceSSDistanceScale = getMax( ( 1.5f - flareLength ) / 1.5f, 0.0f );

   // Scale based on recent visibility changes, fading in or out.
   F32 fadeInOutScale = 1.0f;   
   if (  lightVisible &&
         visDelta < FadeInTime && 
         flareState->occlusion > 0.0f )
      fadeInOutScale = (F32)visDelta / (F32)FadeInTime;
   else if (   !lightVisible && 
               visDelta < FadeOutTime )
      fadeInOutScale = 1.0f - (F32)visDelta / (F32)FadeOutTime;

   // This combined scale influences the size of all elements this effect renders.
   // Note we also add in a scale that is user specified in the Light.
   F32 lightSourceIntensityScale = lightSourceBrightnessScale * 
                                   lightSourceWSDistanceScale * 
                                   lightSourceSSDistanceScale * 
                                   fadeInOutScale * 
                                   flareState->scale *
                                   occlusionFade;

   if ( mIsZero( lightSourceIntensityScale ) )
      return;

   // The baseColor which modulates the color of all elements.
   //
   // These are the factors which affect the "alpha" of the flare effect.
   // Modulate more in as appropriate.
   ColorF baseColor = ColorF::WHITE * lightSourceBrightnessScale * occlusionFade;

   // Setup the vertex buffer for the maximum flare elements.
   const U32 vertCount = 4 * mElementCount;
   if (  flareState->vertBuffer.isNull() || 
         flareState->vertBuffer->mNumVerts != vertCount )
         flareState->vertBuffer.set( GFX, vertCount, GFXBufferTypeDynamic );

   GFXVertexPCT *vert = flareState->vertBuffer.lock();

   const Point2F oneOverTexSize( 1.0f / (F32)mFlareTexture.getWidth(), 1.0f / (F32)mFlareTexture.getHeight() );

   for ( U32 i = 0; i < mElementCount; i++ )
   {      
      // Skip non-zero elements for reflections.
      if ( isReflectPass && mElementDist[i] > 0.0f )
         continue;

      Point3F *basePos = mElementRotate[i] ? rotatedBasePoints : sBasePoints;

      ColorF color( baseColor * mElementTint[i] );
      if ( mElementUseLightColor[i] )
         color *= lightInfo->getColor();
      color.clamp();

      Point3F pos( lightPosSS + flareVec * mElementDist[i] * flareLength );

      const RectF &rect = mElementRect[i];
      Point3F size( rect.extent.x, rect.extent.y, 1.0f );
      size *= mElementScale[i] * mScale * lightSourceIntensityScale;

      AssertFatal( size.x >= 0.0f, "LightFlareData::prepRender - Got a negative element size?" );

      if ( size.x < 100.0f )
      {
         F32 alphaScale = mPow( size.x / 100.0f, 2 );
         color *= alphaScale;
      }

      Point2F texCoordMin, texCoordMax;
      texCoordMin = rect.point * oneOverTexSize;
      texCoordMax = ( rect.point + rect.extent ) * oneOverTexSize;          

      size.x = getMax( size.x, 1.0f );
      size.y = getMax( size.y, 1.0f );
      size *= oneOverViewportExtent;

      vert->color = color;
      vert->point = ( basePos[0] * size ) + pos;      
      vert->texCoord.set( texCoordMin.x, texCoordMax.y );
      vert++;

      vert->color = color;
      vert->point = ( basePos[1] * size ) + pos;
      vert->texCoord.set( texCoordMax.x, texCoordMax.y );
      vert++;

      vert->color = color;
      vert->point = ( basePos[2] * size ) + pos;
      vert->texCoord.set( texCoordMax.x, texCoordMin.y );
      vert++;

      vert->color = color;
      vert->point = ( basePos[3] * size ) + pos;
      vert->texCoord.set( texCoordMin.x, texCoordMin.y );
      vert++;
   }   

   flareState->vertBuffer.unlock();   

   RenderPassManager *rpm = state->getRenderPass();

   // Create and submit the render instance.   
   ParticleRenderInst *ri = rpm->allocInst<ParticleRenderInst>();
   ri->type = RenderPassManager::RIT_Particle;
   ri->vertBuff = &flareState->vertBuffer;
   ri->primBuff = &mFlarePrimBuffer;
   ri->translucentSort = true;
   ri->sortDistSq = ( lightPos - camPos ).lenSquared();
   ri->modelViewProj = &MatrixF::Identity;
   ri->bbModelViewProj = &MatrixF::Identity;
   ri->count = elementCount;
   ri->blendStyle = ParticleRenderInst::BlendGreyscale;
   ri->diffuseTex = mFlareTexture;
   ri->softnessDistance = 1.0f; 
   ri->defaultKey = ri->diffuseTex ? (U32)ri->diffuseTex : (U32)ri->vertBuff; // Sort by texture too.

   // NOTE: Offscreen partical code is currently disabled.
   ri->systemState = PSS_AwaitingHighResDraw;

   rpm->addInst( ri );
}
コード例 #17
0
/**
 * Sets the object the bot is targeting
 *
 * @param targetObject The object to target
 */
void AIPlayer::setAimObject( GameBase *targetObject )
{
   mAimObject = targetObject;
   mTargetInLOS = false;
   mAimOffset = Point3F(0.0f, 0.0f, 0.0f);
}
コード例 #18
0
void SceneManager::_renderScene( SceneRenderState* state, U32 objectMask, SceneZoneSpace* baseObject, U32 baseZone )
{
   AssertFatal( this == gClientSceneGraph, "SceneManager::_buildSceneGraph - Only the client scenegraph can support this call!" );

   PROFILE_SCOPE( SceneGraph_batchRenderImages );

   // In the editor, override the type mask for diffuse passes.

   if( gEditingMission && state->isDiffusePass() )
      objectMask = EDITOR_RENDER_TYPEMASK;

   // Update the zoning state and traverse zones.

   if( getZoneManager() )
   {
      // Update.

      getZoneManager()->updateZoningState();

      // If zone culling isn't disabled, traverse the
      // zones now.

      if( !state->getCullingState().disableZoneCulling() )
      {
         // Find the start zone if we haven't already.

         if( !baseObject )
         {
            getZoneManager()->findZone( state->getCameraPosition(), baseObject, baseZone );
            AssertFatal( baseObject != NULL, "SceneManager::_renderScene - findZone() did not return an object" );
         }

         // Traverse zones starting in base object.

         SceneTraversalState traversalState( &state->getCullingState() );
         PROFILE_START( Scene_traverseZones );
         baseObject->traverseZones( &traversalState, baseZone );
         PROFILE_END();

         // Set the scene render box to the area we have traversed.

         state->setRenderArea( traversalState.getTraversedArea() );
      }
   }

   // Set the query box for the container query.  Never
   // make it larger than the frustum's AABB.  In the editor,
   // always query the full frustum as that gives objects
   // the opportunity to render editor visualizations even if
   // they are otherwise not in view.

   if( !state->getFrustum().getBounds().isOverlapped( state->getRenderArea() ) )
   {
      // This handles fringe cases like flying backwards into a zone where you
      // end up pretty much standing on a zone border and looking directly into
      // its "walls".  In that case the traversal area will be behind the frustum
      // (remember that the camera isn't where visibility starts, it's the near
      // distance).

      return;
   }

   Box3F queryBox = state->getFrustum().getBounds();
   if( !gEditingMission )
   {
      queryBox.minExtents.setMax( state->getRenderArea().minExtents );
      queryBox.maxExtents.setMin( state->getRenderArea().maxExtents );
   }

   PROFILE_START( Scene_cullObjects );

   //TODO: We should split the codepaths here based on whether the outdoor zone has visible space.
   //    If it has, we should use the container query-based path.
   //    If it hasn't, we should fill the object list directly from the zone lists which will usually
   //       include way fewer objects.
   
   // Gather all objects that intersect the scene render box.

   mBatchQueryList.clear();
   getContainer()->findObjectList( queryBox, objectMask, &mBatchQueryList );

   // Cull the list.

   U32 numRenderObjects = state->getCullingState().cullObjects(
      mBatchQueryList.address(),
      mBatchQueryList.size(),
      !state->isDiffusePass() ? SceneCullingState::CullEditorOverrides : 0 // Keep forced editor stuff out of non-diffuse passes.
   );

   //HACK: If the control object is a Player and it is not in the render list, force
   // it into it.  This really should be solved by collision bounds being separate from
   // object bounds; only because the Player class is using bounds not encompassing
   // the actual player object is it that we have this problem in the first place.
   // Note that we are forcing the player object into ALL passes here but such
   // is the power of proliferation of things done wrong.

   GameConnection* connection = GameConnection::getConnectionToServer();
   if( connection )
   {
      Player* player = dynamic_cast< Player* >( connection->getControlObject() );
      if( player )
      {
         mBatchQueryList.setSize( numRenderObjects );
         if( !mBatchQueryList.contains( player ) )
         {
            mBatchQueryList.push_back( player );
            numRenderObjects ++;
         }
      }
   }

   PROFILE_END();

   // Render the remaining objects.

   PROFILE_START( Scene_renderObjects );
   state->renderObjects( mBatchQueryList.address(), numRenderObjects );
   PROFILE_END();

   // Render bounding boxes, if enabled.

   if( smRenderBoundingBoxes && state->isDiffusePass() )
   {
      GFXDEBUGEVENT_SCOPE( Scene_renderBoundingBoxes, ColorI::WHITE );

      GameBase* cameraObject = 0;
      if( connection )
         cameraObject = connection->getCameraObject();

      GFXStateBlockDesc desc;
      desc.setFillModeWireframe();
      desc.setZReadWrite( true, false );

      for( U32 i = 0; i < numRenderObjects; ++ i )
      {
         SceneObject* object = mBatchQueryList[ i ];

         // Skip global bounds object.
         if( object->isGlobalBounds() )
            continue;

         // Skip camera object as we're viewing the scene from it.
         if( object == cameraObject )
            continue;

         const Box3F& worldBox = object->getWorldBox();
         GFX->getDrawUtil()->drawObjectBox(
            desc,
            Point3F( worldBox.len_x(), worldBox.len_y(), worldBox.len_z() ),
            worldBox.getCenter(),
            MatrixF::Identity,
            ColorI::WHITE
         );
      }
   }
}
コード例 #19
0
/**
 * This method calculates the moves for the AI player
 *
 * @param movePtr Pointer to move the move list into
 */
bool AIPlayer::getAIMove(Move *movePtr)
{
   *movePtr = NullMove;

   // Use the eye as the current position.
   MatrixF eye;
   getEyeTransform(&eye);
   Point3F location = eye.getPosition();
   Point3F rotation = getRotation();

   // Orient towards the aim point, aim object, or towards
   // our destination.
   if (mAimObject || mAimLocationSet || mMoveState != ModeStop) 
   {
      // Update the aim position if we're aiming for an object
      if (mAimObject)
         mAimLocation = mAimObject->getPosition() + mAimOffset;
      else
         if (!mAimLocationSet)
            mAimLocation = mMoveDestination;

      F32 xDiff = mAimLocation.x - location.x;
      F32 yDiff = mAimLocation.y - location.y;

      if (!mIsZero(xDiff) || !mIsZero(yDiff)) 
      {
         // First do Yaw
         // use the cur yaw between -Pi and Pi
         F32 curYaw = rotation.z;
         while (curYaw > M_2PI_F)
            curYaw -= M_2PI_F;
         while (curYaw < -M_2PI_F)
            curYaw += M_2PI_F;

         // find the yaw offset
         F32 newYaw = mAtan2( xDiff, yDiff );
         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_PI_F )
            yawDiff -= M_2PI_F;
         else if( yawDiff < -M_PI_F )
            yawDiff += M_2PI_F;

         movePtr->yaw = yawDiff;

         // Next do pitch.
         if (!mAimObject && !mAimLocationSet) 
         {
            // Level out if were just looking at our next way point.
            Point3F headRotation = getHeadRotation();
            movePtr->pitch = -headRotation.x;
         }
         else 
         {
            // This should be adjusted to run from the
            // eye point to the object's center position. Though this
            // works well enough for now.
            F32 vertDist = mAimLocation.z - location.z;
            F32 horzDist = mSqrt(xDiff * xDiff + yDiff * yDiff);
            F32 newPitch = mAtan2( horzDist, vertDist ) - ( M_PI_F / 2.0f );
            if (mFabs(newPitch) > 0.01f) 
            {
               Point3F headRotation = getHeadRotation();
               movePtr->pitch = newPitch - headRotation.x;
            }
         }
      }
   }
   else 
   {
      // Level out if we're not doing anything else
      Point3F headRotation = getHeadRotation();
      movePtr->pitch = -headRotation.x;
   }

   // Move towards the destination
   if (mMoveState != ModeStop) 
   {
      F32 xDiff = mMoveDestination.x - location.x;
      F32 yDiff = mMoveDestination.y - location.y;

      // Check if we should mMove, or if we are 'close enough'
      if (mFabs(xDiff) < mMoveTolerance && mFabs(yDiff) < mMoveTolerance) 
      {
         mMoveState = ModeStop;
         throwCallback("onReachDestination");
      }
      else 
      {
         // Build move direction in world space
         if (mIsZero(xDiff))
            movePtr->y = (location.y > mMoveDestination.y) ? -1.0f : 1.0f;
         else
            if (mIsZero(yDiff))
               movePtr->x = (location.x > mMoveDestination.x) ? -1.0f : 1.0f;
            else
               if (mFabs(xDiff) > mFabs(yDiff)) 
               {
                  F32 value = mFabs(yDiff / xDiff);
                  movePtr->y = (location.y > mMoveDestination.y) ? -value : value;
                  movePtr->x = (location.x > mMoveDestination.x) ? -1.0f : 1.0f;
               }
               else 
               {
                  F32 value = mFabs(xDiff / yDiff);
                  movePtr->x = (location.x > mMoveDestination.x) ? -value : value;
                  movePtr->y = (location.y > mMoveDestination.y) ? -1.0f : 1.0f;
               }

         // Rotate the move into object space (this really only needs
         // a 2D matrix)
         Point3F newMove;
         MatrixF moveMatrix;
         moveMatrix.set(EulerF(0.0f, 0.0f, -(rotation.z + movePtr->yaw)));
         moveMatrix.mulV( Point3F( movePtr->x, movePtr->y, 0.0f ), &newMove );
         movePtr->x = newMove.x;
         movePtr->y = newMove.y;

         // Set movement speed.  We'll slow down once we get close
         // to try and stop on the spot...
         if (mMoveSlowdown) 
         {
            F32 speed = mMoveSpeed;
            F32 dist = mSqrt(xDiff*xDiff + yDiff*yDiff);
            F32 maxDist = 5.0f;
            if (dist < maxDist)
               speed *= dist / maxDist;
            movePtr->x *= speed;
            movePtr->y *= speed;

            mMoveState = ModeSlowing;
         }
         else 
         {
            movePtr->x *= mMoveSpeed;
            movePtr->y *= mMoveSpeed;

            mMoveState = ModeMove;
         }

         if (mMoveStuckTestCountdown > 0)
            --mMoveStuckTestCountdown;
         else
         {
            // We should check to see if we are stuck...
            F32 locationDelta = (location - mLastLocation).len();
            if (locationDelta < mMoveStuckTolerance && mDamageState == Enabled) 
            {
               // If we are slowing down, then it's likely that our location delta will be less than
               // our move stuck tolerance. Because we can be both slowing and stuck
               // we should TRY to check if we've moved. This could use better detection.
               if ( mMoveState != ModeSlowing || locationDelta == 0 )
               {
                  mMoveState = ModeStuck;
                  throwCallback("onMoveStuck");
               }
            }
         }
      }
   }

   // Test for target location in sight if it's an object. The LOS is
   // run from the eye position to the center of the object's bounding,
   // which is not very accurate.
   if (mAimObject) {
      MatrixF eyeMat;
      getEyeTransform(&eyeMat);
      eyeMat.getColumn(3,&location);
      Point3F targetLoc = mAimObject->getBoxCenter();

      // This ray ignores non-static shapes. Cast Ray returns true
      // if it hit something.
      RayInfo dummy;
      if (getContainer()->castRay( location, targetLoc,
            StaticShapeObjectType | StaticObjectType |
            TerrainObjectType, &dummy)) {
         if (mTargetInLOS) {
            throwCallback( "onTargetExitLOS" );
            mTargetInLOS = false;
         }
      }
      else
         if (!mTargetInLOS) {
            throwCallback( "onTargetEnterLOS" );
            mTargetInLOS = true;
         }
   }

   // Replicate the trigger state into the move so that
   // triggers can be controlled from scripts.
   for( int i = 0; i < MaxTriggerKeys; i++ )
      movePtr->trigger[i] = getImageTriggerState(i);

   mLastLocation = location;

   return true;
}
コード例 #20
0
ファイル: terrRender.cpp プロジェクト: 03050903/Torque3D
void TerrainBlock::_updateBaseTexture(bool writeToCache)
{
   if ( !mBaseShader && !_initBaseShader() )
      return;

   // This can sometimes occur outside a begin/end scene.
   const bool sceneBegun = GFX->canCurrentlyRender();
   if ( !sceneBegun )
      GFX->beginScene();

   GFXDEBUGEVENT_SCOPE( TerrainBlock_UpdateBaseTexture, ColorI::GREEN );

   PROFILE_SCOPE( TerrainBlock_UpdateBaseTexture );

   GFXTransformSaver saver;

   const U32 maxTextureSize = GFX->getCardProfiler()->queryProfile( "maxTextureSize", 1024 );

   U32 baseTexSize = getNextPow2( mBaseTexSize );
   baseTexSize = getMin( maxTextureSize, baseTexSize );
   Point2I destSize( baseTexSize, baseTexSize );

   // Setup geometry
   GFXVertexBufferHandle<GFXVertexPT> vb;
   {
      F32 copyOffsetX = 2.0f * GFX->getFillConventionOffset() / (F32)destSize.x;
      F32 copyOffsetY = 2.0f * GFX->getFillConventionOffset() / (F32)destSize.y;

      GFXVertexPT points[4];
      points[0].point = Point3F(1.0 - copyOffsetX, -1.0 + copyOffsetY, 0.0);
      points[0].texCoord = Point2F(1.0, 1.0f);
      points[1].point = Point3F(1.0 - copyOffsetX, 1.0 + copyOffsetY, 0.0);
      points[1].texCoord = Point2F(1.0, 0.0f);
      points[2].point = Point3F(-1.0 - copyOffsetX, -1.0 + copyOffsetY, 0.0);
      points[2].texCoord = Point2F(0.0, 1.0f);
      points[3].point = Point3F(-1.0 - copyOffsetX, 1.0 + copyOffsetY, 0.0);
      points[3].texCoord = Point2F(0.0, 0.0f);

      vb.set( GFX, 4, GFXBufferTypeVolatile );
      GFXVertexPT *ptr = vb.lock();
      if(ptr)
      {
         dMemcpy( ptr, points, sizeof(GFXVertexPT) * 4 );
         vb.unlock();
      }
   }

   GFXTexHandle blendTex;

   // If the base texture is already a valid render target then 
   // use it to render to else we create one.
   if (  mBaseTex.isValid() && 
         mBaseTex->isRenderTarget() &&
         mBaseTex->getFormat() == GFXFormatR8G8B8A8 &&
         mBaseTex->getWidth() == destSize.x &&
         mBaseTex->getHeight() == destSize.y )
      blendTex = mBaseTex;
   else
      blendTex.set( destSize.x, destSize.y, GFXFormatR8G8B8A8, &GFXDefaultRenderTargetProfile, "" );

   GFX->pushActiveRenderTarget();   

   // Set our shader stuff
   GFX->setShader( mBaseShader );
   GFX->setShaderConstBuffer( mBaseShaderConsts );
   GFX->setStateBlock( mBaseShaderSB );
   GFX->setVertexBuffer( vb );

   mBaseTarget->attachTexture( GFXTextureTarget::Color0, blendTex );
   GFX->setActiveRenderTarget( mBaseTarget );

   GFX->clear( GFXClearTarget, ColorI(0,0,0,255), 1.0f, 0 );

   GFX->setTexture( 0, mLayerTex );
   mBaseShaderConsts->setSafe( mBaseLayerSizeConst, (F32)mLayerTex->getWidth() );      

   for ( U32 i=0; i < mBaseTextures.size(); i++ )
   {
      GFXTextureObject *tex = mBaseTextures[i];
      if ( !tex )
         continue;

      GFX->setTexture( 1, tex );

      F32 baseSize = mFile->mMaterials[i]->getDiffuseSize();
      F32 scale = 1.0f;
      if ( !mIsZero( baseSize ) )
         scale = getWorldBlockSize() / baseSize;
      
      // A mistake early in development means that texture
      // coords are not flipped correctly.  To compensate
      // we flip the y scale here.
      mBaseShaderConsts->setSafe( mBaseTexScaleConst, Point2F( scale, -scale ) );
      mBaseShaderConsts->setSafe( mBaseTexIdConst, (F32)i );

      GFX->drawPrimitive( GFXTriangleStrip, 0, 2 );
   }

   mBaseTarget->resolve();
   
   GFX->setShader( NULL );
   //GFX->setStateBlock( NULL ); // WHY NOT?
   GFX->setShaderConstBuffer( NULL );
   GFX->setVertexBuffer( NULL );

   GFX->popActiveRenderTarget();

   // End it if we begun it... Yeehaw!
   if ( !sceneBegun )
      GFX->endScene();

   /// Do we cache this sucker?
   if (mBaseTexFormat == NONE || !writeToCache)
   {
      // We didn't cache the result, so set the base texture
      // to the render target we updated.  This should be good
      // for realtime painting cases.
      mBaseTex = blendTex;
   }
   else if (mBaseTexFormat == DDS)
   {
      String cachePath = _getBaseTexCacheFileName();

      FileStream fs;
      if ( fs.open( _getBaseTexCacheFileName(), Torque::FS::File::Write ) )
      {
         // Read back the render target, dxt compress it, and write it to disk.
         GBitmap blendBmp( destSize.x, destSize.y, false, GFXFormatR8G8B8A8 );
         blendTex.copyToBmp( &blendBmp );

         /*
         // Test code for dumping uncompressed bitmap to disk.
         {
         FileStream fs;
         if ( fs.open( "./basetex.png", Torque::FS::File::Write ) )
         {
         blendBmp.writeBitmap( "png", fs );
         fs.close();
         }         
         }
         */

         blendBmp.extrudeMipLevels();

         DDSFile *blendDDS = DDSFile::createDDSFileFromGBitmap( &blendBmp );
         DDSUtil::squishDDS( blendDDS, GFXFormatDXT1 );

         // Write result to file stream
         blendDDS->write( fs );
         
         delete blendDDS;
      }
      fs.close();
   }
   else
   {
      FileStream stream;
      if (!stream.open(_getBaseTexCacheFileName(), Torque::FS::File::Write))
      {
         mBaseTex = blendTex;
         return;
      }

      GBitmap bitmap(blendTex->getWidth(), blendTex->getHeight(), false, GFXFormatR8G8B8);
      blendTex->copyToBmp(&bitmap);
      bitmap.writeBitmap(formatToExtension(mBaseTexFormat), stream);
   }
}
コード例 #21
0
ファイル: scatterSky.cpp プロジェクト: AkiraofAstra/Torque3D
void ScatterSky::_renderMoon( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat )
{
   if ( !mMoonMatInst )
      return;

   Point3F moonlightPosition = state->getCameraPosition() - /*mLight->getDirection()*/ mMoonLightDir * state->getFarPlane() * 0.9f;
   F32 dist = (moonlightPosition - state->getCameraPosition()).len();

   // worldRadius = screenRadius * dist / worldToScreen
   // screenRadius = worldRadius / dist * worldToScreen

   //
   F32 screenRadius = GFX->getViewport().extent.y * mMoonScale * 0.5f;
   F32 worldRadius = screenRadius * dist / state->getWorldToScreenScale().y;

   // Calculate Billboard Radius (in world units) to be constant, independent of distance.
   // Takes into account distance, viewport size, and specified size in editor

   F32 BBRadius = worldRadius;


   mMatrixSet->restoreSceneViewProjection();

   if ( state->isReflectPass() )
      mMatrixSet->setProjection( state->getSceneManager()->getNonClipProjection() );

   mMatrixSet->setWorld( MatrixF::Identity );

   // Initialize points with basic info
   Point3F points[4];
   points[0] = Point3F(-BBRadius, 0.0, -BBRadius);
   points[1] = Point3F( -BBRadius, 0.0, BBRadius);
   points[2] = Point3F( BBRadius, 0.0,  BBRadius);
   points[3] = Point3F( BBRadius, 0.0,  -BBRadius);

   static const Point2F sCoords[4] =
   {
      Point2F( 0.0f, 0.0f ),
      Point2F( 0.0f, 1.0f ),
      Point2F( 1.0f, 1.0f ),
      Point2F( 1.0f, 0.0f )
   };

   // Get info we need to adjust points
   const MatrixF &camView = state->getCameraTransform();

   // Finalize points
   for(int i = 0; i < 4; i++)
   {
      // align with camera
      camView.mulV(points[i]);
      // offset
      points[i] += moonlightPosition;
   }

   // Vertex color.
   ColorF moonVertColor( 1.0f, 1.0f, 1.0f, mNightInterpolant );

   // Copy points to buffer.

   GFXVertexBufferHandle< GFXVertexPCT > vb;
   vb.set( GFX, 4, GFXBufferTypeVolatile );
   GFXVertexPCT *pVert = vb.lock();

   for ( S32 i = 0; i < 4; i++ )
   {
      pVert->color.set( moonVertColor );
      pVert->point.set( points[i] );
      pVert->texCoord.set( sCoords[i].x, sCoords[i].y );
      pVert++;
   }

   vb.unlock();

   // Setup SceneData struct.

   SceneData sgData;
   sgData.wireframe = GFXDevice::getWireframe();
   sgData.visibility = 1.0f;

   // Draw it

   while ( mMoonMatInst->setupPass( state, sgData ) )
   {
      mMoonMatInst->setTransforms( *mMatrixSet, state );
      mMoonMatInst->setSceneInfo( state, sgData );

      GFX->setVertexBuffer( vb );
      GFX->drawPrimitive( GFXTriangleFan, 0, 2 );
   }
}
コード例 #22
0
bool SceneCullingState::createCullingVolume( const Point3F* vertices, U32 numVertices, SceneCullingVolume::Type type, SceneCullingVolume& outVolume )
{
   const Point3F& viewPos = getCameraState().getViewPosition();
   const Point3F& viewDir = getCameraState().getViewDirection();
   const bool isOrtho = getCullingFrustum().isOrtho();

   //TODO: check if we need to handle penetration of the near plane for occluders specially

   // Allocate space for the clipping planes we generate.  Assume the worst case
   // of every edge generating a plane and, for includers, all edges meeting at
   // steep angles so we need to insert extra planes (the latter is not possible,
   // of course, but it makes things less complicated here).  For occluders, add
   // an extra plane for the near cap.

   const U32 maxPlanes = ( type == SceneCullingVolume::Occluder ? numVertices + 1 : numVertices * 2 );
   PlaneF* planes = allocateData< PlaneF >( maxPlanes );

   // Keep track of the world-space bounds of the polygon.  We use this later
   // to derive some metrics.

   Box3F wsPolyBounds;

   wsPolyBounds.minExtents = Point3F( TypeTraits< F32 >::MAX, TypeTraits< F32 >::MAX, TypeTraits< F32 >::MAX );
   wsPolyBounds.maxExtents = Point3F( TypeTraits< F32 >::MIN, TypeTraits< F32 >::MIN, TypeTraits< F32 >::MIN );

   // For occluders, also keep track of the nearest, and two farthest silhouette points.  We use
   // this later to construct a near capping plane.
   F32 minVertexDistanceSquared = TypeTraits< F32 >::MAX;
   U32 leastDistantVert = 0;

   F32 maxVertexDistancesSquared[ 2 ] = { TypeTraits< F32 >::MIN, TypeTraits< F32 >::MIN };
   U32 mostDistantVertices[ 2 ] = { 0, 0 };

   // Generate the extrusion volume.  For orthographic projections, extrude
   // parallel to the view direction whereas for parallel projections, extrude
   // from the viewpoint.

   U32 numPlanes = 0;
   U32 lastVertex = numVertices - 1;
   bool invert = false;

   for( U32 i = 0; i < numVertices; lastVertex = i, ++ i )
   {
      AssertFatal( numPlanes < maxPlanes, "SceneCullingState::createCullingVolume - Did not allocate enough planes!" );

      const Point3F& v1 = vertices[ i ];
      const Point3F& v2 = vertices[ lastVertex ];

      // Keep track of bounds.

      wsPolyBounds.minExtents.setMin( v1 );
      wsPolyBounds.maxExtents.setMax( v1 );

      // Skip the edge if it's length is really short.

      const Point3F edgeVector = v2 - v1;
      const F32 edgeVectorLenSquared = edgeVector.lenSquared();
      if( edgeVectorLenSquared < 0.025f )
         continue;

      //TODO: might need to do additional checks here for non-planar polygons used by occluders
      //TODO: test for colinearity of edge vector with view vector (occluders only)

      // Create a plane for the edge.

      if( isOrtho )
      {
         // Compute a plane through the two edge vertices and one
         // of the vertices extended along the view direction.

         if( !invert )
            planes[ numPlanes ] = PlaneF( v1, v1 + viewDir, v2 );
         else
            planes[ numPlanes ] = PlaneF( v2, v1 + viewDir, v1 );
      }
      else
      {
         // Compute a plane going through the viewpoint and the two
         // edge vertices.

         if( !invert )
            planes[ numPlanes ] = PlaneF( v1, viewPos, v2 );
         else
            planes[ numPlanes ] = PlaneF( v2, viewPos, v1 );
      }

      numPlanes ++;

      // If this is the first plane that we have created, find out whether
      // the vertex ordering is giving us the plane orientations that we want
      // (facing inside).  If not, invert vertex order from now on.

      if( numPlanes == 1 )
      {
         Point3F center( 0, 0, 0 );
         for( U32 n = 0; n < numVertices; ++ n )
            center += vertices[n];
         center /= numVertices;

         if( planes[numPlanes - 1].whichSide( center ) == PlaneF::Back )
         {
            invert = true;
            planes[ numPlanes - 1 ].invert();
         }
      }

      // For occluders, keep tabs of the nearest, and two farthest vertices.

      if( type == SceneCullingVolume::Occluder )
      {
         const F32 distSquared = ( v1 - viewPos ).lenSquared();
         if( distSquared < minVertexDistanceSquared )
         {
            minVertexDistanceSquared = distSquared;
            leastDistantVert = i;
         }
         if( distSquared > maxVertexDistancesSquared[ 0 ] )
         {
            // Move 0 to 1.
            maxVertexDistancesSquared[ 1 ] = maxVertexDistancesSquared[ 0 ];
            mostDistantVertices[ 1 ] = mostDistantVertices[ 0 ];

            // Replace 0.
            maxVertexDistancesSquared[ 0 ] = distSquared;
            mostDistantVertices[ 0 ] = i;
         }
         else if( distSquared > maxVertexDistancesSquared[ 1 ] )
         {
            // Replace 1.
            maxVertexDistancesSquared[ 1 ] = distSquared;
            mostDistantVertices[ 1 ] = i;
         }
      }
   }

   // If the extrusion produced no useful result, abort.

   if( numPlanes < 3 )
      return false;

   // For includers, test the angle of the edges at the current vertex.
   // If too steep, add an extra plane to improve culling efficiency.

   if( false )//type == SceneCullingVolume::Includer )
   {
      const U32 numOriginalPlanes = numPlanes;
      U32 lastPlaneIndex = numPlanes - 1;

      for( U32 i = 0; i < numOriginalPlanes; lastPlaneIndex = i, ++ i )
      {
         const PlaneF& currentPlane = planes[ i ];
         const PlaneF& lastPlane = planes[ lastPlaneIndex ];

         // Compute the cosine of the angle between the two plane normals.

         const F32 cosAngle = mFabs( mDot( currentPlane, lastPlane ) );

         // The planes meet at increasingly steep angles the more they point
         // in opposite directions, i.e the closer the angle of their normals
         // is to 180 degrees.  Skip any two planes that don't get near that.

         if( cosAngle > 0.1f )
            continue;

         //TODO

         const Point3F addNormals = currentPlane + lastPlane;
         const Point3F crossNormals = mCross( currentPlane, lastPlane );

         Point3F newNormal = currentPlane + lastPlane;//addNormals - mDot( addNormals, crossNormals ) * crossNormals;

         //

         planes[ numPlanes ] = PlaneF( currentPlane.getPosition(), newNormal );
         numPlanes ++;
      }
   }

   // Compute the metrics of the culling volume in relation to the view frustum.
   //
   // For this, we are short-circuiting things slightly.  The correct way (other than doing
   // full screen projections) would be to transform all the polygon points into camera
   // space, lay an AABB around those points, and then find the X and Z extents on the near plane.
   //
   // However, while not as accurate, a faster way is to just project the axial vectors
   // of the bounding box onto both the camera right and up vector.  This gives us a rough
   // estimate of the camera-space size of the polygon we're looking at.
   
   const MatrixF& cameraTransform = getCameraState().getViewWorldMatrix();
   const Point3F cameraRight = cameraTransform.getRightVector();
   const Point3F cameraUp = cameraTransform.getUpVector();

   const Point3F wsPolyBoundsExtents = wsPolyBounds.getExtents();
   
   F32 widthEstimate =
      getMax( mFabs( wsPolyBoundsExtents.x * cameraRight.x ),
         getMax( mFabs( wsPolyBoundsExtents.y * cameraRight.y ),
                 mFabs( wsPolyBoundsExtents.z * cameraRight.z ) ) );

   F32 heightEstimate =
      getMax( mFabs( wsPolyBoundsExtents.x * cameraUp.x ),
         getMax( mFabs( wsPolyBoundsExtents.y * cameraUp.y ),
                 mFabs( wsPolyBoundsExtents.z * cameraUp.z ) ) );

   // If the current camera is a perspective one, divide the two estimates
   // by the distance of the nearest bounding box vertex to the camera
   // to account for perspective distortion.

   if( !isOrtho )
   {
      const Point3F nearestVertex = wsPolyBounds.computeVertex(
         Box3F::getPointIndexFromOctant( - viewDir )
      );

      const F32 distance = ( nearestVertex - viewPos ).len();

      widthEstimate /= distance;
      heightEstimate /= distance;
   }

   // If we are creating an occluder, check to see if the estimates fit
   // our minimum requirements.

   if( type == SceneCullingVolume::Occluder )
   {
      const F32 widthEstimatePercentage = widthEstimate / getCullingFrustum().getWidth();
      const F32 heightEstimatePercentage = heightEstimate / getCullingFrustum().getHeight();

      if( widthEstimatePercentage < smOccluderMinWidthPercentage ||
          heightEstimatePercentage < smOccluderMinHeightPercentage )
         return false; // Reject.
   }

   // Use the area estimate as the volume's sort point.

   const F32 sortPoint = widthEstimate * heightEstimate;

   // Finally, if it's an occluder, compute a near cap.  The near cap prevents objects
   // in front of the occluder from testing positive.  The same could be achieved by
   // manually comparing distances before testing objects but since that would amount
   // to the same checks the plane/AABB tests do, it's easier to just add another plane.
   // Additionally, it gives the benefit of being able to create more precise culling
   // results by angling the plane.

   //NOTE: Could consider adding a near cap for includers too when generating a volume
   //  for the outdoor zone as that may prevent quite a bit of space from being included.
   //  However, given that this space will most likely just be filled with interior
   //  stuff anyway, it's probably not worth it.

   if( type == SceneCullingVolume::Occluder )
   {
      const U32 nearCapIndex = numPlanes;
      planes[ nearCapIndex ] = PlaneF(
         vertices[ mostDistantVertices[ 0 ] ],
         vertices[ mostDistantVertices[ 1 ] ],
         vertices[ leastDistantVert ] );

      // Invert the plane, if necessary.
      if( planes[ nearCapIndex ].whichSide( viewPos ) == PlaneF::Front )
         planes[ nearCapIndex ].invert();

      numPlanes ++;
   }

   // Create the volume from the planes.

   outVolume = SceneCullingVolume(
      type,
      PlaneSetF( planes, numPlanes )
   );
   outVolume.setSortPoint( sortPoint );

   // Done.

   return true;
}
コード例 #23
0
ファイル: flyingVehicle.cpp プロジェクト: Adhdcrazzy/Torque3D
void FlyingVehicle::updateForces(F32 /*dt*/)
{
   PROFILE_SCOPE( FlyingVehicle_UpdateForces );

   MatrixF currPosMat;
   mRigid.getTransform(&currPosMat);
   mRigid.atRest = false;

   Point3F massCenter;
   currPosMat.mulP(mDataBlock->massCenter,&massCenter);

   Point3F xv,yv,zv;
   currPosMat.getColumn(0,&xv);
   currPosMat.getColumn(1,&yv);
   currPosMat.getColumn(2,&zv);
   F32 speed = mRigid.linVelocity.len();

   Point3F force  = Point3F(0, 0, sFlyingVehicleGravity * mRigid.mass * mGravityMod);
   Point3F torque = Point3F(0, 0, 0);

   // Drag at any speed
   force  -= mRigid.linVelocity * mDataBlock->minDrag;
   torque -= mRigid.angMomentum * mDataBlock->rotationalDrag;

   // Auto-stop at low speeds
   if (speed < mDataBlock->maxAutoSpeed) {
      F32 autoScale = 1 - speed / mDataBlock->maxAutoSpeed;

      // Gyroscope
      F32 gf = mDataBlock->autoAngularForce * autoScale;
      torque -= xv * gf * mDot(yv,Point3F(0,0,1));

      // Manuevering jets
      F32 sf = mDataBlock->autoLinearForce * autoScale;
      force -= yv * sf * mDot(yv, mRigid.linVelocity);
      force -= xv * sf * mDot(xv, mRigid.linVelocity);
   }

   // Hovering Jet
   F32 vf = -sFlyingVehicleGravity * mRigid.mass * mGravityMod;
   F32 h  = getHeight();
   if (h <= 1) {
      if (h > 0) {
         vf -= vf * h * 0.1;
      } else {
         vf += mDataBlock->jetForce * -h;
      }
   }
   force += zv * vf;

   // Damping "surfaces"
   force -= xv * mDot(xv,mRigid.linVelocity) * mDataBlock->horizontalSurfaceForce;
   force -= zv * mDot(zv,mRigid.linVelocity) * mDataBlock->verticalSurfaceForce;

   // Turbo Jet
   if (mJetting) {
      if (mThrustDirection == ThrustForward)
         force += yv * mDataBlock->jetForce * mCeilingFactor;
      else if (mThrustDirection == ThrustBackward)
         force -= yv * mDataBlock->jetForce * mCeilingFactor;
      else
         force += zv * mDataBlock->jetForce * mDataBlock->vertThrustMultiple * mCeilingFactor;
   }

   // Maneuvering jets
   force += yv * (mThrust.y * mDataBlock->maneuveringForce * mCeilingFactor);
   force += xv * (mThrust.x * mDataBlock->maneuveringForce * mCeilingFactor);

   // Steering
   Point2F steering;
   steering.x = mSteering.x / mDataBlock->maxSteeringAngle;
   steering.x *= mFabs(steering.x);
   steering.y = mSteering.y / mDataBlock->maxSteeringAngle;
   steering.y *= mFabs(steering.y);
   torque -= xv * steering.y * mDataBlock->steeringForce;
   torque -= zv * steering.x * mDataBlock->steeringForce;

   // Roll
   torque += yv * steering.x * mDataBlock->steeringRollForce;
   F32 ar = mDataBlock->autoAngularForce * mDot(xv,Point3F(0,0,1));
   ar -= mDataBlock->rollForce * mDot(xv, mRigid.linVelocity);
   torque += yv * ar;

   // Add in force from physical zones...
   force += mAppliedForce;

   // Container buoyancy & drag
   force -= Point3F(0, 0, 1) * (mBuoyancy * sFlyingVehicleGravity * mRigid.mass * mGravityMod);
   force -= mRigid.linVelocity * mDrag;

   //
   mRigid.force  = force;
   mRigid.torque = torque;
}
コード例 #24
0
void ForestWind::processTick()
{
   PROFILE_SCOPE( ForestWind_ProcessTick );

   const F32 deltaTime = 0.032f;
   const U32 simTime = Sim::getCurrentTime();
   
   Point2F finalVec( 0, 0 );
   Point2F windDir( mParent->mWindDirection.x, mParent->mWindDirection.y );

   if ( mLastGustTime < simTime )
   {
      Point2F turbVec( 0, 0 );
      if ( mLastGustTime < simTime + (mParent->mWindTurbulenceFrequency * 1000.0f) )
         turbVec = (mRandom.randF() * mParent->mWindTurbulenceStrength) * windDir;

      mLastGustTime = simTime + (mParent->mWindGustFrequency * 1000.0f);
      Point2F gustVec = (mRandom.randF() * mParent->mWindGustStrength + mRandom.randF() * mParent->mWindGustWobbleStrength) * windDir;

      finalVec += gustVec + turbVec;
      //finalVec.normalizeSafe();
   }
   
   //bool rotationChange = false;

   if ( mLastYawTime < simTime )
   {
      mLastYawTime = simTime + (mParent->mWindGustYawFrequency * 1000.0f);
      F32 rotateAmt = mRandom.randF() * mParent->mWindGustYawAngle + mRandom.randF() * mParent->mWindGustWobbleStrength;
      
      if ( mRandom.randF() <= 0.5f )
         rotateAmt = -rotateAmt;

      rotateAmt = mDegToRad( rotateAmt );

      if ( rotateAmt > M_2PI_F )
         rotateAmt -= M_2PI_F;
      else if ( rotateAmt < -M_2PI_F )
         rotateAmt += M_2PI_F;

      mTargetYawAngle = rotateAmt;

      //finalVec.rotate( rotateAmt );
      mCurrentTarget.rotate( rotateAmt );
   }
   
   //mCurrentTarget.normalizeSafe();

   if ( mCurrentTarget.isZero() || mCurrentInterp >= 1.0f )
   {
      mCurrentInterp = 0;
      mCurrentTarget.set( 0, 0 );
   
      Point2F windDir( mDirection.x, mDirection.y );
      windDir.normalizeSafe();

      mCurrentTarget = finalVec + windDir;
   }
   else
   {
      mCurrentInterp += deltaTime;
      mCurrentInterp = mClampF( mCurrentInterp, 0.0f, 1.0f );
      mDirection.interpolate( mDirection, Point3F( mCurrentTarget.x, mCurrentTarget.y, 0 ), mCurrentInterp );
      //F32 rotateAmt = mLerp( 0, mTargetYawAngle, mCurrentInterp );

      //mTargetYawAngle -= rotateAmt;

      //Point2F dir( mDirection.x, mDirection.y );
      //if ( mTargetYawAngle > 0.0f )
        // dir.rotate( rotateAmt );

      //mDirection.set( dir.x, dir.y, 0 );
   }
}
コード例 #25
0
   "         position = %position;\n"
   "         dataBlock = %effectDataBlock;\n"
   "      };\n"
   "   }\n"
   "}\n\n"
   "// schedule an explosion\n"
   "schedule(1000, 0, ServerPlayExplosion, \"0 0 0\", GrenadeLauncherExplosion);\n"
   "@endtsexample"
);

#define MaxLightRadius 20

MRandomLCG sgRandom(0xdeadbeef);


DefineEngineFunction(calcExplosionCoverage, F32, (Point3F pos, S32 id, U32 covMask),(Point3F(0.0f,0.0f,0.0f), NULL, NULL),
   "@brief Calculates how much an explosion effects a specific object.\n\n"
   "Use this to determine how much damage to apply to objects based on their "
   "distance from the explosion's center point, and whether the explosion is "
   "blocked by other objects.\n\n"
   "@param pos Center position of the explosion.\n"
   "@param id Id of the object of which to check coverage.\n"
   "@param covMask Mask of object types that may block the explosion.\n"
   "@return Coverage value from 0 (not affected by the explosion) to 1 (fully affected)\n\n"
   "@tsexample\n"
   "// Get the position of the explosion.\n"
   "%position = %explosion.getPosition();\n\n"
   "// Set a list of TypeMasks (defined in gameFunctioncs.cpp), seperated by the | character.\n"
   "%TypeMasks = $TypeMasks::StaticObjectType | $TypeMasks::ItemObjectType\n\n"
   "// Acquire the damage value from 0.0f - 1.0f.\n"
   "%coverage = calcExplosionCoverage( %position, %sceneObject, %TypeMasks );\n\n"
コード例 #26
0
void OcclusionVolume::buildSilhouette( const SceneCameraState& cameraState, Vector< Point3F >& outPoints )
{
   // Extract the silhouette of the polyhedron.  This works differently
   // depending on whether we project orthogonally or in perspective.

   TempAlloc< U32 > indices( mPolyhedron.getNumPoints() );
   U32 numPoints;

   if( cameraState.getFrustum().isOrtho() )
   {
      // Transform the view direction into object space.

      Point3F osViewDir;
      getWorldTransform().mulV( cameraState.getViewDirection(), &osViewDir );

      // And extract the silhouette.

      SilhouetteExtractorOrtho< PolyhedronType > extractor( mPolyhedron );
      numPoints = extractor.extractSilhouette( osViewDir, indices, indices.size );
   }
   else
   {
      // Create a transform to go from view space to object space.

      MatrixF camView( true );
      camView.scale( Point3F( 1.0f / getScale().x, 1.0f / getScale().y, 1.0f / getScale().z ) );
      camView.mul( getRenderWorldTransform() );
      camView.mul( cameraState.getViewWorldMatrix() );

      // Do a perspective-correct silhouette extraction.

      numPoints = mSilhouetteExtractor.extractSilhouette(
         camView,
         indices, indices.size );
   }

   // If we haven't yet, transform the polyhedron's points
   // to world space.

   if( mTransformDirty )
   {
      const U32 numPoints = mPolyhedron.getNumPoints();
      const PolyhedronType::PointType* points = getPolyhedron().getPoints();

      mWSPoints.setSize( numPoints );
      for( U32 i = 0; i < numPoints; ++ i )
      {
         Point3F p = points[ i ];
         p.convolve( getScale() );
         getTransform().mulP( p, &mWSPoints[ i ] );
      }

      mTransformDirty = false;
   }

   // Now store the points.

   outPoints.setSize( numPoints );
   for( U32 i = 0; i < numPoints; ++ i )
      outPoints[ i ] = mWSPoints[ indices[ i ] ];
}
コード例 #27
0
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);
      }
   }
}
コード例 #28
0
bool SceneObject::collideBox(const Point3F &start, const Point3F &end, RayInfo *info)
{
   const F32 * pStart = (const F32*)start;
   const F32 * pEnd = (const F32*)end;
   const F32 * pMin = (const F32*)mObjBox.minExtents;
   const F32 * pMax = (const F32*)mObjBox.maxExtents;

   F32 maxStartTime = -1;
   F32 minEndTime = 1;
   F32 startTime;
   F32 endTime;

   // used for getting normal
   U32 hitIndex = 0xFFFFFFFF;
   U32 side;

   // walk the axis
   for(U32 i = 0; i < 3; i++)
   {
      //
      if(pStart[i] < pEnd[i])
      {
         if(pEnd[i] < pMin[i] || pStart[i] > pMax[i])
            return(false);

         F32 dist = pEnd[i] - pStart[i];

         startTime = (pStart[i] < pMin[i]) ? (pMin[i] - pStart[i]) / dist : -1;
         endTime = (pEnd[i] > pMax[i]) ? (pMax[i] - pStart[i]) / dist : 1;
         side = 1;
      }
      else
      {
         if(pStart[i] < pMin[i] || pEnd[i] > pMax[i])
            return(false);

         F32 dist = pStart[i] - pEnd[i];
         startTime = (pStart[i] > pMax[i]) ? (pStart[i] - pMax[i]) / dist : -1;
         endTime = (pEnd[i] < pMin[i]) ? (pStart[i] - pMin[i]) / dist : 1;
         side = 0;
      }

      //
      if(startTime > maxStartTime)
      {
         maxStartTime = startTime;
         hitIndex = i * 2 + side;
      }
      if(endTime < minEndTime)
         minEndTime = endTime;
      if(minEndTime < maxStartTime)
         return(false);
   }

   // fail if inside
   if(maxStartTime < 0.f)
      return(false);

   //
   static Point3F boxNormals[] = {
      Point3F( 1, 0, 0),
      Point3F(-1, 0, 0),
      Point3F( 0, 1, 0),
      Point3F( 0,-1, 0),
      Point3F( 0, 0, 1),
      Point3F( 0, 0,-1),
   };

   //
   AssertFatal(hitIndex != 0xFFFFFFFF, "SceneObject::collideBox");
   info->t = maxStartTime;
   info->object = this;
   mObjToWorld.mulV(boxNormals[hitIndex], &info->normal);
   info->material = 0;
   return(true);
}
コード例 #29
0
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;
}
コード例 #30
0
ファイル: lightFlareData.cpp プロジェクト: AlkexGas/Torque3D
void LightFlareState::clear()
{
   visChangedTime = 0;
   visible = false;
   scale = 1.0f;
   fullBrightness = 1.0f;
   lightMat = MatrixF::Identity;
   lightInfo = NULL;
   worldRadius = -1.0f;
   occlusion = -1.0f;
}

Point3F LightFlareData::sBasePoints[] =
{ 
   Point3F( -0.5, 0.5, 0.0 ), 
   Point3F( -0.5, -0.5, 0.0 ),   
   Point3F( 0.5, -0.5, 0.0 ),  
   Point3F( 0.5, 0.5, 0.0 ) 
};


IMPLEMENT_CO_DATABLOCK_V1( LightFlareData );

ConsoleDocClass( LightFlareData,
   "@brief Defines a light flare effect usable by scene lights.\n\n"      
   
   "%LightFlareData is a datablock which defines a type of flare effect. "
   "This may then be referenced by other classes which support the rendering "
   "of a flare: Sun, ScatterSky, LightBase.\n\n"