Пример #1
0
/** Resolve collision with an immovable object
   Computes & applies the collision impulse needed to keep the body
   from penetrating the given surface.
*/
bool Rigid::resolveCollision(const Point3F& p, const Point3F &normal)
{
   atRest = false;
   Point3F v,r;
   getOriginVector(p,&r);
   getVelocity(r,&v);
   F32 n = -mDot(v,normal);
   if (n >= 0.0f) {

      // Collision impulse, straight forward force stuff.
      F32 d = getZeroImpulse(r,normal);
      F32 j = n * (1.0f + restitution) * d;
      Point3F impulse = normal * j;

      // Friction impulse, calculated as a function of the
      // amount of force it would take to stop the motion
      // perpendicular to the normal.
      Point3F uv = v + (normal * n);
      F32 ul = uv.len();
      if (ul) {
         uv /= -ul;
         F32 u = ul * getZeroImpulse(r,uv);
         j *= friction;
         if (u > j)
            u = j;
         impulse += uv * u;
      }

      //
      applyImpulse(r,impulse);
   }
   return true;
}
Пример #2
0
bool PxSingleActor::prepRenderImage(   SceneState *state,
                                          const U32 stateKey,
                                          const U32 startZone, 
                                          const bool modifyBaseState )
{
   if ( !mShapeInstance || !state->isObjectRendered(this) )
      return false;

   Point3F cameraOffset;
   getTransform().getColumn(3,&cameraOffset);
   cameraOffset -= state->getDiffuseCameraPosition();
   F32 dist = cameraOffset.len();
   if ( dist < 0.01f )
      dist = 0.01f;

   F32 invScale = (1.0f/getMax(getMax(getScale().x,getScale().y),getScale().z));
   dist *= invScale;
   S32 dl = mShapeInstance->setDetailFromDistance( state, dist );
   if (dl<0)
      return false;

   renderObject( state );

   return false;
}
Пример #3
0
void Etherform::updateCameraPos(F32 delta)
{
	//
	// Update 3rd person camera position.
	//

	F32 min,max;
	Point3F offset;
	MatrixF rot;
	this->getCameraParameters(&min,&max,&offset,&rot);

	Point3F vec = mCameraTargetPos - mCameraPos;
	F32    dist = vec.len();

	if(dist == 0)
	{
		// Catch camera position up to its target position.
		mCameraPos = mCameraTargetPos;
	}
	else if(dist > max)
	{
		// Catch camera up to max allowed dist from target position.
		vec.normalize(); vec.neg();
		mCameraPos = mCameraTargetPos + vec * max;
	}
	else
	{
		// Move camera pos towards its target pos.
#if 0
		F32 speed = mDataBlock->accelerationForce;
		speed *= 1 - (1/vec.lenSquared());

		vec.normalize();
		mCameraPos += vec * speed * delta;
#else
		//F32 speedScale = this->getVelocity().len() / mDataBlock->accelerationForce;
		F32 speedScale = 4; //mDataBlock->accelerationForce / 2;
		F32 distScale = 1 - (1/vec.lenSquared());
		vec *= speedScale * distScale * delta;
		if(vec.len() > dist)
			mCameraPos = mCameraTargetPos;
		else
			mCameraPos += vec;
#endif
	}
}
Пример #4
0
//----------------------------------------------------------------------------
void Item::updateWorkingCollisionSet(const U32 mask, const F32 dt)
{
   // It is assumed that we will never accelerate more than 10 m/s for gravity...
   //
   Point3F scaledVelocity = mVelocity * dt;
   F32 len    = scaledVelocity.len();
   F32 newLen = len + (10 * dt);

   // Check to see if it is actually necessary to construct the new working list,
   //  or if we can use the cached version from the last query.  We use the x
   //  component of the min member of the mWorkingQueryBox, which is lame, but
   //  it works ok.
   bool updateSet = false;

   Box3F convexBox = mConvex.getBoundingBox(getTransform(), getScale());
   F32 l = (newLen * 1.1) + 0.1;  // from Convex::updateWorkingList
   convexBox.minExtents -= Point3F(l, l, l);
   convexBox.maxExtents += Point3F(l, l, l);

   // Check containment
   {
      if (mWorkingQueryBox.minExtents.x != -1e9)
      {
         if (mWorkingQueryBox.isContained(convexBox) == false)
         {
            // Needed region is outside the cached region.  Update it.
            updateSet = true;
         }
         else
         {
            // We can leave it alone, we're still inside the cached region
         }
      }
      else
      {
         // Must update
         updateSet = true;
      }
   }

   // Actually perform the query, if necessary
   if (updateSet == true)
   {
      mWorkingQueryBox = convexBox;
      mWorkingQueryBox.minExtents -= Point3F(2 * l, 2 * l, 2 * l);
      mWorkingQueryBox.maxExtents += Point3F(2 * l, 2 * l, 2 * l);

      disableCollision();
      if (mCollisionObject)
         mCollisionObject->disableCollision();

      mConvex.updateWorkingList(mWorkingQueryBox, mask);

      if (mCollisionObject)
         mCollisionObject->enableCollision();
      enableCollision();
   }
}
Пример #5
0
void CelAnimMesh::setCommonScale( Shape::Mesh & otherMesh )
{
   CelAnimMesh *potherMesh = dynamic_cast<CelAnimMesh *>(&otherMesh);
   AssertFatal(potherMesh,
      "TS::CelAnimMesh::setCommonScale:  meshes not same type");

#if 0 
   // array of unpacked verts -- points only
   Point3F *unpackedVerts = new Point3F[fVerts.size()];
   int v;
   for (v=0;v<fVerts.size();v++)
      fVerts[v].getPoint(unpackedVerts[v],fScale,fOrigin);

   Point3F *otherUnpackedVerts = new Point3F[potherMesh->fVerts.size()];
   for (v=0;v<potherMesh->fVerts.size();v++)
      potherMesh->fVerts[v].getPoint(otherUnpackedVerts[v],potherMesh->fScale,potherMesh->fOrigin);

   // get minVert and maxVert for setting new fScale, fOrigin, and fRadius
   Point3F minVert = unpackedVerts[0];
   Point3F maxVert = unpackedVerts[0];
   for (v=1;v<fVerts.size();v++)
   {
      minVert.setMin( unpackedVerts[v] );
      maxVert.setMax( unpackedVerts[v] );
   }
   for (v=0;v<potherMesh->fVerts.size();v++)
   {
      minVert.setMin( otherUnpackedVerts[v] );
      maxVert.setMax( otherUnpackedVerts[v] );
   }

   // figure new fOrigin, fScale, and fRadius
   Point3F newOrigin = minVert;
   maxVert -= minVert;
   Point3F newScale( maxVert.x/255.0f, maxVert.y/255.0f, maxVert.z/255.0f);
   float newRadius = maxVert.len();

   // re-pack this shapes verts     
   int i;
   Point3F temp;
   for (i=0;i<fVerts.size();i++)
      fVerts[i].setPoint(unpackedVerts[i],newScale,newOrigin);
   fOrigin=newOrigin;
   fScale=newScale;
   fRadius=newRadius;

   // re-pack other shapes verts
   for (i=0;i<potherMesh->fVerts.size();i++)
      potherMesh->fVerts[i].setPoint(otherUnpackedVerts[i],newScale,newOrigin);
   potherMesh->fOrigin=fOrigin;
   potherMesh->fScale=newScale;
   potherMesh->fRadius=newRadius;

   delete [] unpackedVerts;
   delete [] otherUnpackedVerts;
#endif      
}
Пример #6
0
void Point3NormalizeValidator::validateType(SimObject *object, void *typePtr)
{
    Point3F *v = (Point3F *) typePtr;
    const F32 len = v->len();
    if(!mIsEqual(len, 1.0f))
    {
        consoleError(object, "Vector length must be %g", length);
        *v *= length / len;
    }
}
bool WindEmitter::findBest(   const Point3F& cameraPos, 
                              const VectorF& cameraDir,
                              F32 viewDistance,
                              U32 maxResults,
                              WindEmitterList* results )
{
   PROFILE_START(WindEmitter_findBest);

   // Build a sphere from the camera point.
	SphereF cameraSphere;
   cameraSphere.center = cameraPos;
   cameraSphere.radius = viewDistance;

   // Collect the active spheres within the camera space and score them.
   WindEmitterList best;
   WindEmitterList::iterator iter = smAllEmitters.begin();
   for ( ; iter != smAllEmitters.end(); iter++ )
   {        
      const SphereF& sphere = *(*iter);

      // Skip any spheres outside of our camera range or that are disabled.
      if ( !(*iter)->mEnabled || !cameraSphere.isIntersecting( sphere ) )
         continue;

      // Simple score calculation...
      //
      // score = ( radius / distance to camera ) * dot( cameraDir, vector from camera to sphere )
      //
      Point3F vect = sphere.center - cameraSphere.center;
      F32 dist = vect.len();
      (*iter)->mScore = dist * sphere.radius;
      vect /= getMax( dist, 0.001f );
      (*iter)->mScore *= mDot( vect, cameraDir );

      best.push_back( *iter );
   }

   // Sort the results by score!
   dQsort( best.address(), best.size(), sizeof(WindEmitter*), &WindEmitter::_sortByScore );

   // Clip the results to the max requested.
   if ( best.size() > maxResults )
      best.setSize( maxResults );

   // Merge the results and return.
   results->merge( best );

   PROFILE_END(); // WindEmitter_findBest

   return best.size() > 0;
}
Пример #8
0
void Etherform::updateWorkingCollisionSet()
{
   // First, we need to adjust our velocity for possible acceleration.  It is assumed
   // that we will never accelerate more than 20 m/s for gravity, plus 10 m/s for
   // jetting, and an equivalent 10 m/s for jumping.  We also assume that the
   // working list is updated on a Tick basis, which means we only expand our
   // box by the possible movement in that tick.
   Point3F scaledVelocity = mVelocity * TickSec;
   F32 len    = scaledVelocity.len();
   F32 newLen = len + (10.0f * TickSec);

   // Check to see if it is actually necessary to construct the new working list,
   // or if we can use the cached version from the last query.  We use the x
   // component of the min member of the mWorkingQueryBox, which is lame, but
   // it works ok.
   bool updateSet = false;

   Box3F convexBox = mConvex.getBoundingBox(getTransform(), getScale());
   F32 l = (newLen * 1.1f) + 0.1f;  // from Convex::updateWorkingList
   const Point3F  lPoint( l, l, l );
   convexBox.minExtents -= lPoint;
   convexBox.maxExtents += lPoint;

   // Check containment
   if (mWorkingQueryBox.minExtents.x != -1e9f)
   {
      if (mWorkingQueryBox.isContained(convexBox) == false)
         // Needed region is outside the cached region.  Update it.
         updateSet = true;
   }
   else
   {
      // Must update
      updateSet = true;
   }
   
   // Actually perform the query, if necessary
   if (updateSet == true)
   {
      const Point3F  twolPoint( 2.0f * l, 2.0f * l, 2.0f * l );
      mWorkingQueryBox = convexBox;
      mWorkingQueryBox.minExtents -= twolPoint;
      mWorkingQueryBox.maxExtents += twolPoint;

      disableCollision();
      mConvex.updateWorkingList(mWorkingQueryBox,
         isGhost() ? sClientCollisionContactMask : sServerCollisionContactMask);
      enableCollision();
   }
}
Пример #9
0
void PxSingleActor::_onContact(  NxActor *ourActor, 
                                    NxActor *hitActor, 
                                    SceneObject *hitObject,
                                    const Point3F &hitPoint,
                                    const Point3F &impactForce )
{
   if ( isGhost() )
      return;

   String strHitPos = String::ToString( "%g %g %g", hitPoint.x, hitPoint.y, hitPoint.z );
   String strImpactVec = String::ToString( "%g %g %g", impactForce.x, impactForce.y, impactForce.z );
   String strImpactForce = String::ToString( "%g", impactForce.len() );
      
   Con::executef( mDataBlock, "onCollision", getIdString(), 
      hitObject ? hitObject->scriptThis() : "", 
      strHitPos.c_str(), strImpactVec.c_str(), strImpactForce.c_str() );
}
Пример #10
0
// This is for panning the viewport camera.
void GuiMaterialPreview::setTranslate(S32 modifier, F32 xstep, F32 ystep)
{
	F32 transstep = (modifier & SI_SHIFT ? mTransStep : (mTransStep*mTranMult));

	F32 nominalDistance = 20.0;
	Point3F vec = mCameraPos;
	vec -= mOrbitPos;
	transstep *= vec.len() / nominalDistance;

	if (modifier & SI_PRIMARY_CTRL)
	{
		mOrbitRelPos.x += ( xstep * transstep );
		mOrbitRelPos.y += ( ystep * transstep );
	}
	else
	{
		mOrbitRelPos.x += ( xstep * transstep );
		mOrbitRelPos.z += ( ystep * transstep );
	}
}
Пример #11
0
void Lightning::scheduleThunder(Strike* newStrike)
{
   AssertFatal(isClientObject(), "Lightning::scheduleThunder: server objects should not enter this version of the function");

   // If no thunder sounds, don't schedule anything!
   if (mDataBlock->numThunders == 0)
      return;

   GameConnection* connection = GameConnection::getConnectionToServer();
   if (connection) {
      MatrixF cameraMatrix;

      if (connection->getControlCameraTransform(0, &cameraMatrix)) {
         Point3F worldPos;
         cameraMatrix.getColumn(3, &worldPos);

         worldPos.x -= newStrike->xVal;
         worldPos.y -= newStrike->yVal;
         worldPos.z  = 0.0f;

         F32 dist = worldPos.len();
         F32 t    = dist / 330.0f;

         // Ok, we need to schedule a random strike sound t secs in the future...
         //
         if (t <= 0.03f) {
            // If it's really close, just play it...
            U32 thunder = sgLightningRand.randI(0, mDataBlock->numThunders - 1);
            SFX->playOnce(mDataBlock->thunderSounds[thunder]);
         } else {
            Thunder* pThunder = new Thunder;
            pThunder->tRemaining = t;
            pThunder->next       = mThunderListHead;
            mThunderListHead     = pThunder;
         }
      }
   }
}
Пример #12
0
void TSStatic::prepRenderImage( SceneRenderState* state )
{
   if( !mShapeInstance )
      return;
	//WLE - Vince
	//Lod preloading
    GameConnection* connection = GameConnection::getConnectionToServer();
	if (connection && !connection->didFirstRender)
		{
		TSRenderState rdata;
		rdata.setSceneState( state );
		rdata.setFadeOverride( 1.0f );
		rdata.setOriginSort( mUseOriginSort );
		for (S32 i = mShapeInstance->getSmallestVisibleDL(); i >= 0; i-- )
			{
			mShapeInstance->setCurrentDetail( i );
			   
			mShapeInstance->render( rdata );
			}
		}

   Point3F cameraOffset;
   getRenderTransform().getColumn(3,&cameraOffset);
   cameraOffset -= state->getDiffuseCameraPosition();
   F32 dist = cameraOffset.len();
   if (dist < 0.01f)
      dist = 0.01f;

   if (mUseAlphaLod)
   {
      mAlphaLOD = 1.0f;
      if ((mAlphaLODStart < mAlphaLODEnd) && mAlphaLODStart > 0.1f)
      {
         if (mInvertAlphaLod)
		 {
            if (dist <= mAlphaLODStart)
			{
               return;
			}
  
            if (dist < mAlphaLODEnd)
			{
               mAlphaLOD = ((dist - mAlphaLODStart) / (mAlphaLODEnd - mAlphaLODStart));
			}
         }
         else
		 {
            if (dist >= mAlphaLODEnd)
			{
               return;
			}
  
            if (dist > mAlphaLODStart)
			{
               mAlphaLOD -= ((dist - mAlphaLODStart) / (mAlphaLODEnd - mAlphaLODStart));
			}
         }
      }
   }

   F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z));   

   if ( mForceDetail == -1 )
      mShapeInstance->setDetailFromDistance( state, dist * invScale );
   else
      mShapeInstance->setCurrentDetail( mForceDetail );

   if ( mShapeInstance->getCurrentDetail() < 0 )
      return;

   GFXTransformSaver saver;
   
   // Set up our TS render state.
   TSRenderState rdata;
   rdata.setSceneState( state );
   rdata.setFadeOverride( 1.0f );
   rdata.setOriginSort( mUseOriginSort );

   // If we have submesh culling enabled then prepare
   // the object space frustum to pass to the shape.
   Frustum culler;
   if ( mMeshCulling )
   {
      culler = state->getCullingFrustum();
      MatrixF xfm( true );
      xfm.scale( Point3F::One / getScale() );
      xfm.mul( getRenderWorldTransform() );
      xfm.mul( culler.getTransform() );
      culler.setTransform( xfm );
      rdata.setCuller( &culler );
   }

   // We might have some forward lit materials
   // so pass down a query to gather lights.
   LightQuery query;
   query.init( getWorldSphere() );
   rdata.setLightQuery( &query );

   MatrixF mat = getRenderTransform();
   mat.scale( mObjScale );
   GFX->setWorldMatrix( mat );

   mShapeInstance->animate();
   if(mShapeInstance)
   {
      if (mUseAlphaLod)
      {
         mShapeInstance->setAlphaAlways(mAlphaLOD);
         S32 s = mShapeInstance->mMeshObjects.size();
         
         for(S32 x = 0; x < s; x++)
         {
            mShapeInstance->mMeshObjects[x].visible = mAlphaLOD;
         }
      }
   }
   mShapeInstance->render( rdata );

   if ( mRenderNormalScalar > 0 )
   {
      ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
      ri->renderDelegate.bind( this, &TSStatic::_renderNormals );
      ri->type = RenderPassManager::RIT_Editor;
      state->getRenderPass()->addInst( ri );
   }
}
Пример #13
0
   void terrTexGen( vertexType vtype, Point4F *clipmapMapping, const MatrixF &blockTransform, const Point3F &cameraPosition, LightInfo *light, SceneState * state)
   {
      PROFILE_SCOPE(Terrain_TexGen);
      SceneManager * sceneManager = state->getSceneManager();
      Point3F relative;
      const F32 blockTexCoordScale = 1.0f / (TerrainRender::mCurrentBlock->getSquareSize() * TerrainBlock::BlockSize);
      // Apply texgen to the new verts...
      if (vtype == vertexTypeFullClipMapping)
      {
         for(U32 i=0; i<mCurVertex; i++)
         {
            mVertexStore[i].texCoord.x = mVertexStore[i].point.x * blockTexCoordScale;
            mVertexStore[i].texCoord.y = mVertexStore[i].point.y * blockTexCoordScale;
         }
      }
      else if (vtype == vertexTypeSingleTextureClipMapping)
      {
         // Compute the fixedfunction vert stuff now
         AssertFatal(clipmapMapping != NULL, "TerrBatch::end - vertexTypeSingleTextureClipMapping requires clipmapMapping variable!");
         const F32 fadeConstant = 3.0f;
         const F32 blockTexCoordScale2 = blockTexCoordScale * clipmapMapping->z;
         for(U32 i=0; i<mCurVertex; i++)
         {
            mVertexStorePCNT[i].point = mVertexStore[i].point;
            mVertexStorePCNT[i].normal = mVertexStore[i].normal;
            mVertexStorePCNT[i].texCoord.x = mVertexStore[i].point.x * blockTexCoordScale2;
            mVertexStorePCNT[i].texCoord.y = mVertexStore[i].point.y * blockTexCoordScale2;
            relative.x = mVertexStorePCNT[i].texCoord.x - clipmapMapping->x;
            relative.y = mVertexStorePCNT[i].texCoord.y - clipmapMapping->y;
            relative.z = 0;
            // note: this uses 128.0f - instead of 255.0f - to hide some
            // transition artifacts at the edges (which are not visible
            // in the shader path due to its use of /2 in the vertex
            // shader and saturate(fade*2) in the pixel shader, which
            // allows sharp transitions to be interpolated more cleanly)
            mVertexStorePCNT[i].color.set(255, 255, 255, (U8)mClampF(128.0f - (relative.len() * (2.0f * fadeConstant) - (fadeConstant - 1.0f)) * 255.0f, 0.0f, 255.0f));
         }
      }
      else if (vtype == vertexTypeDLight)
      {
         // Compute the fixedfunction vert stuff now
         AssertFatal(clipmapMapping != NULL, "TerrBatch::end - vertexTypeDLight requires clipmapMapping variable!");
         AssertFatal(light != NULL, "TerrBatch::end - vertexTypeDLight requires light variable!");
         AssertFatal(light->mRadius > 0, "TerrBatch::end - vertexTypeDLight requires light->mRadius > 0!");
         const F32 blockTexCoordScale2 = blockTexCoordScale * clipmapMapping->z;
         const F32 heightOffset = sceneManager->getFogHeightOffset();
         const F32 inverseHeightRange = sceneManager->getFogInvHeightRange();
         const F32 inverseVisibleDistanceMod = 1.0f / sceneManager->getVisibleDistanceMod();
         Point3F worldPoint;
         const F32 lightRadius = light->mRadius;
         const Point3F lightPosition = light->mPos;
         F32 intensity;
         const F32 inverseLightRadius = 1.0f / lightRadius;
         // note: this imitates sgLightingModel only very loosely for
         // performance reasons, it does look very similar to the shader path
         for(U32 i=0; i<mCurVertex; i++)
         {
            mVertexStorePCNTT[i].point = mVertexStore[i].point;
            mVertexStorePCNTT[i].normal = mVertexStore[i].normal;
            mVertexStorePCNTT[i].texCoord[0].x = mVertexStore[i].point.x * blockTexCoordScale2;
            mVertexStorePCNTT[i].texCoord[0].y = mVertexStore[i].point.y * blockTexCoordScale2;
            blockTransform.mulP(mVertexStore[i].point, &worldPoint);
            relative = worldPoint - cameraPosition;
            mVertexStorePCNTT[i].texCoord[1].x = 1.0 - (relative.len() * inverseVisibleDistanceMod);
            mVertexStorePCNTT[i].texCoord[1].y = (worldPoint.z - heightOffset) * inverseHeightRange;
            relative = worldPoint - lightPosition;
            intensity = getMax(1.0f - relative.len() * inverseLightRadius, 0.0f);
            intensity = 512.0f * intensity;
            if (intensity > 0)
               mVertexStorePCNTT[i].color.set((U8)getMin(light->mColor.red * intensity, 255.0f), (U8)getMin(light->mColor.green * intensity, 255.0f), (U8)getMin(light->mColor.blue * intensity, 255.0f), 255);
            else
               mVertexStorePCNTT[i].color.set(0, 0, 0, 255);
         }
      }
      else if (vtype == vertexTypeFog)
      {
         const F32 heightOffset = sceneManager->getFogHeightOffset();
         const F32 inverseHeightRange = sceneManager->getFogInvHeightRange();
         const F32 inverseVisibleDistanceMod = 1.0f / sceneManager->getVisibleDistanceMod();
         Point3F worldPoint;
         for(U32 i=0; i<mCurVertex; i++)
         {
            mVertexStorePCNT[i].point = mVertexStore[i].point;
            mVertexStorePCNT[i].normal = mVertexStore[i].normal;
            blockTransform.mulP(mVertexStore[i].point, &worldPoint);
            relative = worldPoint - cameraPosition;
            mVertexStorePCNT[i].texCoord.x = 1.0 - (relative.len() * inverseVisibleDistanceMod);
            mVertexStorePCNT[i].texCoord.y = (worldPoint.z - heightOffset) * inverseHeightRange;
            mVertexStorePCNT[i].color.set(255, 255, 255, 255);
         }
      }
      // The only time 'vertexTypeDetail' is used is during a fixed-function detail pass.
      else if( vtype == vertexTypeDetail )
      {
         // Get detail distance squared to save us from sqrt
         const F32 detailDistanceSquared = TerrainRender::mCurrentBlock->mDetailDistance * TerrainRender::mCurrentBlock->mDetailDistance;

         // Detail Brightness done via assignment of color values
         const U8 colorByte = mClamp( 255 * TerrainRender::mCurrentBlock->mDetailBrightness, 0, 255 );

         Point3F worldPoint;
         for( U32 i = 0; i < mCurVertex; i++ )
         {
            mVertexStorePCNT[i].point = mVertexStore[i].point;
            mVertexStorePCNT[i].normal = mVertexStore[i].normal;
            mVertexStorePCNT[i].texCoord.x = mVertexStore[i].point.x * blockTexCoordScale;
            mVertexStorePCNT[i].texCoord.y = mVertexStore[i].point.y * blockTexCoordScale;

            // Transform vertex into world space
            blockTransform.mulP( mVertexStore[i].point, &worldPoint );
            relative = worldPoint - cameraPosition;

            // Alpha
            const F32 alpha = TerrainRender::mCurrentBlock->mDetailBrightness * ( 1.0f - ( relative.lenSquared() / detailDistanceSquared ) );

            // Assign alpha value to vert so the detail texture blend fades
            mVertexStorePCNT[i].color.set( colorByte, colorByte, colorByte, mClamp( alpha * 255, 0, 255 ) );
         }
      }
      else
      {
         for(U32 i=0; i<mCurVertex; i++)
         {
            mVertexStorePCNT[i].point = mVertexStore[i].point;
            mVertexStorePCNT[i].normal = mVertexStore[i].normal;
            mVertexStorePCNT[i].texCoord.x = mVertexStore[i].point.x * blockTexCoordScale;
            mVertexStorePCNT[i].texCoord.y = mVertexStore[i].point.y * blockTexCoordScale;
            mVertexStorePCNT[i].color.set(255, 255, 255, 255);
         }
      }
   }
Пример #14
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);
   }
}
Пример #15
0
// warning: a work in progress...not tested yet
bool 
CelAnimMesh::collideBox(int frameIndex,
                        const TMat3F & trans,       // from box to mesh space (box center to origin)
                        const TMat3F & invTrans,    // from mesh to box space
                        const Point3F &radii,
                        CollisionSurface & cs) const
{
   cs;

   int hitface = -1;
   float hitDepth;
   Point3F hitNormal;
   float overlap;

   AssertFatal( fFrames.size() > 0, "Shape must have at least one frame." );
   AssertFatal( frameIndex >= 0 && frameIndex < fFrames.size(),
                "TS::CelAnimMesh: frame index out of range" );
                
   // get the frame struct:
   const Frame *frm = &fFrames[frameIndex];
   int fv = frm->fFirstVert;
   const Point3F *pScale = &frm->fScale;
   const Point3F *pOrigin = &frm->fOrigin;

   int i;
   Point3F v[3],tv[3]; // tv is work space for m_polyOBox...
   for (i=0;i<fFaces.size();i++)
   {
      const Face & theFace = fFaces[i];
      fVerts[theFace.fVIP[0].fVertexIndex+fv].getPoint(v[0],*pScale,*pOrigin);
      fVerts[theFace.fVIP[1].fVertexIndex+fv].getPoint(v[1],*pScale,*pOrigin);
      fVerts[theFace.fVIP[2].fVertexIndex+fv].getPoint(v[2],*pScale,*pOrigin);

      // build the normal
      Point3F normal;
      m_normal(v[0],v[1],v[2],normal);

      if (!m_polyOBox(radii,trans,invTrans,normal,v,tv,3,overlap))
         continue;

/*
      // build the normal
      Point3F normal;
      m_normal(v1,v2,v3,normal);

      float planeDist = m_dot(normal,v1);
      float negBoxDist = m_dot(normal,trans.p); // negative of dist of box from origin
      if (planeDist+negBoxDist<0.0f) // back-face from box center
         continue;

      // does the face's plane intersect the box
      float overlap;
      if (!m_planeOBox(bRadii,trans,normal,planeDist,overlap))
         continue;

      Point3F tv1,tv2,tv3,tMin,tMax;
      m_mul(v1,invTrans,&tv1);
      m_mul(v2,invTrans,&tv2);
      m_mul(v3,invTrans,&tv3);
      tMin=tv1;
      tMin.setMin(tv2);
      tMin.setMin(tv3);
      tMax=tv1;
      tMax.setMax(tv2);
      tMax.setMax(tv3);

      if (tMin.x>bRadii.x)
         continue;
      if (tMax.x<-bRadii.x)
         continue;
      if (tMin.y>bRadii.y)
         continue;
      if (tMax.y<-bRadii.y)
         continue;
      if (tMin.z>bRadii.z)
         continue;
      if (tMax.z<-bRadii.z)
         continue;
*/

      {
         // collision
         hitface = i;
         hitNormal = normal;
         hitDepth = overlap/normal.len();
      }
   }
   hitNormal,hitDepth;
   return hitface!=-1;
}
Пример #16
0
bool CelAnimMesh::collideSphere( int frameIndex, 
                                 const Point3F & center, float radius, 
                                 CollisionSurfaceList & csl) const
{
   AssertFatal( fFrames.size() > 0, "Shape must have at least one frame." );
   AssertFatal( frameIndex >= 0 && frameIndex < fFrames.size(),
                "TS::CelAnimMesh: frame index out of range" );
                
   // get the frame struct:
   const Frame *frm = &fFrames[frameIndex];
   int fv = frm->fFirstVert;
   const Point3F *pScale = &frm->fScale;
   const Point3F *pOrigin = &frm->fOrigin;

   bool gotHit=false;

   int i;
   Point3F v[3];
   for (i=0;i<fFaces.size();i++)
   {
      const Face & theFace = fFaces[i];
      fVerts[theFace.fVIP[0].fVertexIndex+fv].getPoint(v[0],*pScale,*pOrigin);
      fVerts[theFace.fVIP[1].fVertexIndex+fv].getPoint(v[1],*pScale,*pOrigin);
      fVerts[theFace.fVIP[2].fVertexIndex+fv].getPoint(v[2],*pScale,*pOrigin);

      // build the normal and distance from origin of face plane
      Point3F normal;
      m_normal(v[0],v[1],v[2],normal);
      float norm=normal.len();
      if (norm==0.0f) // can happen if a face gets scrunched during animation
         continue;
      normal *= 1.0f/norm;

      // distance from origin of plane and parallel plane containing sphere center
      float dSphere = m_dot(normal,center);
      float dPlane = m_dot(normal,v[0]);
      float dist = dSphere-dPlane;
      if (dist<0) // ignore back facing planes
         continue;

      if (dist>=radius) // whole plane outside of sphere
         continue;

      // intersection of face plane and sphere is a circle on face plane
      // with center p (below) and radius circleRad (below)
      Point3F p;
      p.x = center.x - dist * normal.x;
      p.y = center.y - dist * normal.y;
      p.z = center.z - dist * normal.z;
      float circleRad2 = radius*radius - dist*dist; // square of circle radius

      // check to see if p is inside face (in case whole circle inside face)
      if (m_pointInTriangle(p,normal,v[0],v[1],v[2]))
      {
         // add entry to cil
         csl.increment();
         CollisionSurface & info = csl.last();
         info.surface=i;
         info.material = theFace.fMaterial;
         info.position = p;
         info.normal = normal;
         info.distance = dist;
         gotHit=true;
         continue;
      }

      // go through each edge, check to see if it intersects inside of circle
      // if so, add collision info
      for (int j=0;j<3;j++)
      {
         const Point3F & pivotVert = v[j];
         Point3F edge;
         edge.x = v[(j+1) % 3].x - pivotVert.x;
         edge.y = v[(j+1) % 3].y - pivotVert.y;
         edge.z = v[(j+1) % 3].z - pivotVert.z;

         Point3F radialLine;
         radialLine.x = p.x - pivotVert.x;
         radialLine.y = p.y - pivotVert.y;
         radialLine.z = p.z - pivotVert.z;

         float edgeLen=edge.len();
         if (edgeLen==0.0f)
            continue;
         edge *= 1.0f/edgeLen;

         // get length of projection of radial line onto edge line
         float projRadialToEdgeDist = m_dot(radialLine,edge);

         // find point at which perp. to edge from circle center hits edge line
         Point3F intPoint;
         intPoint.x = pivotVert.x + projRadialToEdgeDist * edge.x;
         intPoint.y = pivotVert.y + projRadialToEdgeDist * edge.y;
         intPoint.z = pivotVert.z + projRadialToEdgeDist * edge.z;
         float distToIntersect2 = (p.x-intPoint.x)*(p.x-intPoint.x) +
                            (p.y-intPoint.y)*(p.y-intPoint.y) +
                            (p.z-intPoint.z)*(p.z-intPoint.z);

         // is whole line outside circle
         if (distToIntersect2>circleRad2)
            continue;

         // length of half-cord formed by edge line
//       float halfcord = sqrt(circleRad2 - distToIntersect2);
         float halfcord2 = circleRad2 - distToIntersect2;

         // check to see if line lands inside of circle
//       if ( (projRadialToEdgeDist < 0.0f-halfcord) || 
//          (projRadialToEdgeDist > halfcord+edgeLen) )
//          continue;
         if (projRadialToEdgeDist < 0.0f)
         {
            if (projRadialToEdgeDist*projRadialToEdgeDist>halfcord2)
               continue;
         }
         else if (projRadialToEdgeDist>edgeLen)
         {
            float tmpF = projRadialToEdgeDist-edgeLen;
            if (tmpF*tmpF>halfcord2)
               continue;
         }

         // we know we hit now...
         // where exactly did we hit, shift intersect point onto edge to form hitPoint
         if (projRadialToEdgeDist < 0.0f)
            projRadialToEdgeDist = 0.0f;
         else if (projRadialToEdgeDist > edgeLen)
            projRadialToEdgeDist = edgeLen;
         Point3F hitPoint;
         hitPoint.x = pivotVert.x + projRadialToEdgeDist * edge.x;
         hitPoint.y = pivotVert.y + projRadialToEdgeDist * edge.y;
         hitPoint.z = pivotVert.z + projRadialToEdgeDist * edge.z;

         // add entry to cil
         csl.increment();
         CollisionSurface & info = csl.last();
         info.surface=i;
         info.material = theFace.fMaterial;
         info.position = hitPoint;
         info.normal = normal;
         info.distance = dist;
         gotHit=true;
         break;
      }
   }
   return gotHit;
}
Пример #17
0
bool CelAnimMesh::collideTube( int frameIndex, const Point3F & a, const Point3F &b, float radius,
                                       CollisionSurface & cs, float minTime) const
{
   minTime;

   // hitTime holds the current smallest...
   float hitTime = cs.time;
   int hitFace = -1;
   Point3F hitPoint;

   AssertFatal( fFrames.size() > 0, "Shape must have at least one frame." );
   AssertFatal( frameIndex >= 0 && frameIndex < fFrames.size(),
                "TS::CelAnimMesh: frame index out of range" );
                
   // get the frame struct:
   const Frame *frm = &fFrames[frameIndex];
   int fv = frm->fFirstVert;
   const Point3F *pScale = &frm->fScale;
   const Point3F *pOrigin = &frm->fOrigin;
   
   Point3F tubeVect;
   tubeVect.x = b.x - a.x;
   tubeVect.y = b.y - a.y;
   tubeVect.z = b.z - a.z;
   float tubeLen = tubeVect.len();
   float invTubeLen = 1.0f/tubeLen;

   // tubeVect will hold unit length vector pointing down tube
   tubeVect *= invTubeLen;
   float vectDotA = m_dot(tubeVect,a);

   // inverse radius squared for edgeInTube routine
   float invRadius2 = 1.0f / (radius*radius);

   int i;
   workVerts.setSize(fnVertsPerFrame);
   workRs.setSize(fnVertsPerFrame);
   workTs.setSize(fnVertsPerFrame);
   bool gotNormal;
   for (i=0;i<fFaces.size();i++)
   {
      const Face & theFace = fFaces[i];
      int idx1 = theFace.fVIP[0].fVertexIndex;
      int idx2 = theFace.fVIP[1].fVertexIndex;
      int idx3 = theFace.fVIP[2].fVertexIndex;

      Point3F &v1=workVerts[idx1];
      Point3F &v2=workVerts[idx2];
      Point3F &v3=workVerts[idx3];

      Point3F &R1=workRs[idx1];
      Point3F &R2=workRs[idx2];
      Point3F &R3=workRs[idx3];
      
      float &t1=workTs[idx1];
      float &t2=workTs[idx2];
      float &t3=workTs[idx3];

      if (!(v1Recycled&faceReuseFlags[i]))
      {
         fVerts[idx1+fv].getPoint(v1,*pScale,*pOrigin);
         // distance of vertex down the tube
         t1 = m_dot(v1,tubeVect) - vectDotA;
         // projection of vertex onto tube cross-section (centered on origin)
         R1.x = v1.x - a.x - t1 * tubeVect.x;
         R1.y = v1.y - a.y - t1 * tubeVect.y;
         R1.z = v1.z - a.z - t1 * tubeVect.z;
      }

      if (!(v2Recycled&faceReuseFlags[i]))
      {
         fVerts[idx2+fv].getPoint(v2,*pScale,*pOrigin);
         // distance of vertex down the tube
         t2 = m_dot(v2,tubeVect) - vectDotA;
         // projection of vertex onto tube cross-section (centered on origin)
         R2.x = v2.x - a.x - t2 * tubeVect.x;
         R2.y = v2.y - a.y - t2 * tubeVect.y;
         R2.z = v2.z - a.z - t2 * tubeVect.z;
      }

      if (!(v3Recycled&faceReuseFlags[i]))
      {
         fVerts[idx3+fv].getPoint(v3,*pScale,*pOrigin);
         // distance of vertex down the tube
         t3 = m_dot(v3,tubeVect) - vectDotA;
         // projection of vertex onto tube cross-section (centered on origin)
         R3.x = v3.x - a.x - t3 * tubeVect.x;
         R3.y = v3.y - a.y - t3 * tubeVect.y;
         R3.z = v3.z - a.z - t3 * tubeVect.z;
      }

      bool gotHit=false;
      if (!(e1Recycled&faceReuseFlags[i]))
      {
         if (t1<=t2)
            gotHit = edgeInTube(R1,R2,t1,t2,radius,invRadius2,invTubeLen,hitTime,hitPoint);
         else
            gotHit = edgeInTube(R2,R1,t2,t1,radius,invRadius2,invTubeLen,hitTime,hitPoint);
      }

      if (!(e2Recycled&faceReuseFlags[i]))
      {
         if (t2<=t3)                                          
            gotHit |= edgeInTube(R2,R3,t2,t3,radius,invRadius2,invTubeLen,hitTime,hitPoint);
         else                                                 
            gotHit |= edgeInTube(R3,R2,t3,t2,radius,invRadius2,invTubeLen,hitTime,hitPoint);
      }

      if (!(e3Recycled&faceReuseFlags[i]))
      {
         if (t3<=t1)
            gotHit |= edgeInTube(R3,R1,t3,t1,radius,invRadius2,invTubeLen,hitTime,hitPoint);
         else
            gotHit |= edgeInTube(R1,R3,t1,t3,radius,invRadius2,invTubeLen,hitTime,hitPoint);
      }

      if (gotHit)
      {
         hitPoint.x += tubeLen * hitTime * tubeVect.x + a.x;
         hitPoint.y += tubeLen * hitTime * tubeVect.y + a.y;
         hitPoint.z += tubeLen * hitTime * tubeVect.z + a.z;
         hitFace=i;
         gotNormal=false;
      }

      // now check if tube goes through center of face w/o hitting any edges
      if (m_pointInTriangle(Point3F(0.0f,0.0f,0.0f),tubeVect,R1,R2,R3))
      {
         // build the normal
         Point3F normal;
         m_normal(v1,v2,v3,normal);
         // now we need to find hitTime
         float d = m_dot(normal,v3); // distance of plane from origin
         float denom = m_dot(normal,tubeVect) * tubeLen;
         if (denom>=0.0f) // back face, we can ignore
            continue;
         float absT = d - m_dot(normal,a);
         if (absT<=hitTime*denom) // denom is neg.
            continue;

         // ok, a real collision, set ci variables...
         hitTime=absT/denom;
         hitFace=i;
         cs.normal=normal;
         gotNormal=true;
         hitPoint.x = a.x + hitTime * tubeLen * tubeVect.x;
         hitPoint.y = a.y + hitTime * tubeLen * tubeVect.y;
         hitPoint.z = a.z + hitTime * tubeLen * tubeVect.z;
      }
   }

   if (hitFace>=0)
   {
      const Face & theFace = fFaces[hitFace];
      if (!gotNormal)
      {
         Point3F &v1=workVerts[theFace.fVIP[0].fVertexIndex];
         Point3F &v2=workVerts[theFace.fVIP[1].fVertexIndex];
         Point3F &v3=workVerts[theFace.fVIP[2].fVertexIndex];

         // build the normal
         Point3F v13,v23;
         v13.x = v1.x-v3.x;
         v13.y = v1.y-v3.y;
         v13.z = v1.z-v3.z;
         v23.x = v2.x-v3.x;
         v23.y = v2.y-v3.y;
         v23.z = v2.z-v3.z;
         m_cross(v23,v13,&cs.normal);
      }
      cs.material=theFace.fMaterial;
      cs.surface=hitFace;
      cs.time=hitTime;
      cs.position=hitPoint;
      // cs.distance ??
      return true;
   }
   return false;
}
Пример #18
0
void TSStatic::prepRenderImage( SceneRenderState* state )
{
   if( !mShapeInstance )
      return;

   Point3F cameraOffset;
   getRenderTransform().getColumn(3,&cameraOffset);
   cameraOffset -= state->getDiffuseCameraPosition();
   F32 dist = cameraOffset.len();
   if (dist < 0.01f)
      dist = 0.01f;

   if (mUseAlphaFade)
   {
      mAlphaFade = 1.0f;
      if ((mAlphaFadeStart < mAlphaFadeEnd) && mAlphaFadeStart > 0.1f)
      {
         if (mInvertAlphaFade)
         {
            if (dist <= mAlphaFadeStart)
            {
               return;
            }
            if (dist < mAlphaFadeEnd)
            {
               mAlphaFade = ((dist - mAlphaFadeStart) / (mAlphaFadeEnd - mAlphaFadeStart));
            }
         }
         else
         {
            if (dist >= mAlphaFadeEnd)
            {
               return;
            }
            if (dist > mAlphaFadeStart)
            {
               mAlphaFade -= ((dist - mAlphaFadeStart) / (mAlphaFadeEnd - mAlphaFadeStart));
            }
         }
      }
   }

   F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z));   

   // If we're currently rendering our own reflection we
   // don't want to render ourselves into it.
   if ( mCubeReflector.isRendering() )
      return;


   if ( mForceDetail == -1 )
      mShapeInstance->setDetailFromDistance( state, dist * invScale );
   else
      mShapeInstance->setCurrentDetail( mForceDetail );

   if ( mShapeInstance->getCurrentDetail() < 0 )
      return;

   GFXTransformSaver saver;
   
   // Set up our TS render state.
   TSRenderState rdata;
   rdata.setSceneState( state );
   rdata.setFadeOverride( 1.0f );
   rdata.setOriginSort( mUseOriginSort );

   if ( mCubeReflector.isEnabled() )
      rdata.setCubemap( mCubeReflector.getCubemap() );

   // Acculumation
   rdata.setAccuTex(mAccuTex);

   // If we have submesh culling enabled then prepare
   // the object space frustum to pass to the shape.
   Frustum culler;
   if ( mMeshCulling )
   {
      culler = state->getCullingFrustum();
      MatrixF xfm( true );
      xfm.scale( Point3F::One / getScale() );
      xfm.mul( getRenderWorldTransform() );
      xfm.mul( culler.getTransform() );
      culler.setTransform( xfm );
      rdata.setCuller( &culler );
   }

   // We might have some forward lit materials
   // so pass down a query to gather lights.
   LightQuery query;
   query.init( getWorldSphere() );
   rdata.setLightQuery( &query );

   MatrixF mat = getRenderTransform();
   mat.scale( mObjScale );
   GFX->setWorldMatrix( mat );

   if ( state->isDiffusePass() && mCubeReflector.isEnabled() && mCubeReflector.getOcclusionQuery() )
   {
       RenderPassManager *pass = state->getRenderPass();
       OccluderRenderInst *ri = pass->allocInst<OccluderRenderInst>();  
       
       ri->type = RenderPassManager::RIT_Occluder;
       ri->query = mCubeReflector.getOcclusionQuery();
       mObjToWorld.mulP( mObjBox.getCenter(), &ri->position );
       ri->scale.set( mObjBox.getExtents() );
       ri->orientation = pass->allocUniqueXform( mObjToWorld ); 
       ri->isSphere = false;
       state->getRenderPass()->addInst( ri );
   }

   mShapeInstance->animate();
   if(mShapeInstance)
   {
      if (mUseAlphaFade)
      {
         mShapeInstance->setAlphaAlways(mAlphaFade);
         S32 s = mShapeInstance->mMeshObjects.size();
         
         for(S32 x = 0; x < s; x++)
         {
            mShapeInstance->mMeshObjects[x].visible = mAlphaFade;
         }
      }
   }
   mShapeInstance->render( rdata );

   if ( mRenderNormalScalar > 0 )
   {
      ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
      ri->renderDelegate.bind( this, &TSStatic::_renderNormals );
      ri->type = RenderPassManager::RIT_Editor;
      state->getRenderPass()->addInst( ri );
   }
}
Пример #19
0
F32 GameBase::getUpdatePriority(CameraScopeQuery *camInfo, U32 updateMask, S32 updateSkips)
{
   TORQUE_UNUSED(updateMask);

   // Calculate a priority used to decide if this object
   // will be updated on the client.  All the weights
   // are calculated 0 -> 1  Then weighted together at the
   // end to produce a priority.
   Point3F pos;
   getWorldBox().getCenter(&pos);
   pos -= camInfo->pos;
   F32 dist = pos.len();
   if (dist == 0.0f) dist = 0.001f;
   pos *= 1.0f / dist;

   // Weight based on linear distance, the basic stuff.
   F32 wDistance = (dist < camInfo->visibleDistance)?
      1.0f - (dist / camInfo->visibleDistance): 0.0f;

   // Weight by field of view, objects directly in front
   // will be weighted 1, objects behind will be 0
   F32 dot = mDot(pos,camInfo->orientation);
   //Winterleaf Modification
   //bool inFov = dot > camInfo->cosFov;
   bool inFov = dot > (cos(  (camInfo->fov + 40) >360?360:camInfo->fov + 40)/2);  
   //Winterleaf Modification


   F32 wFov = inFov? 1.0f: 0;

   // Weight by linear velocity parallel to the viewing plane
   // (if it's the field of view, 0 if it's not).
   F32 wVelocity = 0.0f;
   if (inFov)
   {
      Point3F vec;
      mCross(camInfo->orientation,getVelocity(),&vec);
      wVelocity = (vec.len() * camInfo->fov) /
         (camInfo->fov * camInfo->visibleDistance);
      if (wVelocity > 1.0f)
         wVelocity = 1.0f;
   }

   // Weight by interest.
   F32 wInterest;
   if (getTypeMask() & PlayerObjectType)
      wInterest = 0.75f;
   else if (getTypeMask() & ProjectileObjectType)
   {
      // Projectiles are more interesting if they
      // are heading for us.
      wInterest = 0.30f;
      F32 dot = -mDot(pos,getVelocity());
      if (dot > 0.0f)
         wInterest += 0.20 * dot;
   }
   else
   {
      if (getTypeMask() & ItemObjectType)
         wInterest = 0.25f;
      else
         // Everything else is less interesting.
         wInterest = 0.0f;
   }

   // Weight by updateSkips
   F32 wSkips = updateSkips * 0.5;

   // Calculate final priority, should total to about 1.0f
   //
   return
      wFov       * sUpFov +
      wDistance  * sUpDistance +
      wVelocity  * sUpVelocity +
      wSkips     * sUpSkips +
      wInterest  * sUpInterest;
}
Пример #20
0
bool
xDistributedPoint3F::updateValue(Point3F value,xTimeType currentTime)
{


	mLastTime = mCurrentTime;
	mCurrentTime = currentTime;
	mLastDeltaTime = mCurrentTime - mLastTime;
	
	mLastValue = mCurrentValue;
    mCurrentValue = value;
	mDifference = mCurrentValue - mLastValue;
	
	mThresoldTicker +=mLastDeltaTime;

	float lengthDiff = fabsf(mDifference.len());
	float timeDiffMs = ((float)mThresoldTicker) / 1000.f;
	

	

	int flags  = getFlags();
	flags =E_DP_OK;
	bool result  = false;

	if (this->getPropertyInfo()->mPredictionType == E_PTYPE_PREDICTED)
	{
		if (lengthDiff > getPredictionSettings()->getMinDifference() )
		{
			if (mThresoldTicker2 > getPredictionSettings()->getMinSendTime())
			{
				
				flags =E_DP_NEEDS_SEND;	
				result   = true ;
				

				//xLogger::xLog(ELOGINFO,XL_START,"mThresoldTicker2: %f",mThresoldTicker2);
			}
		}

		Point3F serverDiff  = mCurrentValue-mLastServerValue ;
		
		if (  fabsf( serverDiff.len()) > getPredictionSettings()->getMinDifference() )
		{
			if (mThresoldTicker2 > (getPredictionSettings()->getMinSendTime() * 0.2f) )
			{
				flags =E_DP_NEEDS_SEND;	
				result   = true ;
				//xLogger::xLog(ELOGINFO,XL_START,"mThresoldTicker2: %f",mThresoldTicker2);
			}
		}


		if (mThresoldTicker2 > getPredictionSettings()->getMinSendTime())
		{
			mThresoldTicker2  = 0 ;
			mThresoldTicker  = 0;
		}
	}

	if (getPropertyInfo()->mPredictionType == E_PTYPE_RELIABLE)
	{
		flags =E_DP_NEEDS_SEND;	
		result   = true ;
		mLastValue = value;
		mCurrentValue = value;
	}

	setFlags(flags);
	return result;
}
Пример #21
0
void TSStatic::prepRenderImage( SceneRenderState* state )
{
   if( !mShapeInstance )
      return;

   Point3F cameraOffset;
   getRenderTransform().getColumn(3,&cameraOffset);
   cameraOffset -= state->getDiffuseCameraPosition();
   F32 dist = cameraOffset.len();
   if (dist < 0.01f)
      dist = 0.01f;

   F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z));   

   if ( mForceDetail == -1 )
      mShapeInstance->setDetailFromDistance( state, dist * invScale );
   else
      mShapeInstance->setCurrentDetail( mForceDetail );

   if ( mShapeInstance->getCurrentDetail() < 0 )
      return;

   GFXTransformSaver saver;
   
   // Set up our TS render state.
   TSRenderState rdata;
   rdata.setSceneState( state );
   rdata.setFadeOverride( 1.0f );
   rdata.setOriginSort( mUseOriginSort );

   // If we have submesh culling enabled then prepare
   // the object space frustum to pass to the shape.
   Frustum culler;
   if ( mMeshCulling )
   {
      culler = state->getCullingFrustum();
      MatrixF xfm( true );
      xfm.scale( Point3F::One / getScale() );
      xfm.mul( getRenderWorldTransform() );
      xfm.mul( culler.getTransform() );
      culler.setTransform( xfm );
      rdata.setCuller( &culler );
   }

   // We might have some forward lit materials
   // so pass down a query to gather lights.
   LightQuery query;
   query.init( getWorldSphere() );
   rdata.setLightQuery( &query );

   MatrixF mat = getRenderTransform();
   mat.scale( mObjScale );
   GFX->setWorldMatrix( mat );

   mShapeInstance->animate();
   mShapeInstance->render( rdata );

   if ( mRenderNormalScalar > 0 )
   {
      ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
      ri->renderDelegate.bind( this, &TSStatic::_renderNormals );
      ri->type = RenderPassManager::RIT_Editor;
      state->getRenderPass()->addInst( ri );
   }
}
Пример #22
0
bool Player::initResources(GameBase::GameBaseData *in_data)
{
   data = dynamic_cast<PlayerData *>(in_data);

   if(!Parent::initResources(in_data))
      return false;

	updateImageMass();
	setDrag(data->drag);
	setDensity(data->density);

	int rnode = image.shape->getShape().findNode("dummyalways root");
	const TMat3F& rmat = image.shape->getTransform(rnode);
	image.shape->insertOverride("lowerback",0,&PlayerViewOverride);
	image.shape->insertOverride("lowerback",1,const_cast<TMat3F*>(&rmat));
	image.shape->setOverride(2);

	// 
	myThread = createThread (0);
   viewThread = Parent::createThread(0);
   viewThread->setPriority(-1);

   looksSequence = viewThread->GetSequenceIndex("looks");
   crouchLooksSequence = viewThread->GetSequenceIndex("crouch looks");

   if(crouchLooksSequence == -1)
      crouchLooksSequence = looksSequence;

   AssertFatal(looksSequence != -1, "DOH!");
   viewThread->SetSequence( looksSequence, 0.0 );

   damageThread = 0;
   int i;
   for (i = 0; i < Player::NUM_ANIMS; i ++)
	{
		animIndex[i] = myThread->GetSequenceIndex((char *) data->animData[i].name);
      if(animIndex[i] == -1)
         animIndex[i] = 0;
   }

	Point3F pos;
	clearAnimTransform ();
   for (int j = 0; j < Player::NUM_ANIMS; j ++)
	{
      if((j >= ANIM_MOVE_FIRST && j <= ANIM_MOVE_LAST) ||
         (j >= ANIM_CROUCH_MOVE_FIRST && j <= ANIM_CROUCH_MOVE_LAST))
      {
   		myThread->setTimeScale(1.0);
   		myThread->SetSequence(animIndex[j]);
   		myThread->AdvanceTime(1.0);
   		myThread->UpdateSubscriberList();
			image.shape->animateRoot();
   		pos = getAnimTransform();
         offsetList[j].dist = pos.len();
         offsetList[j].dir = pos;
      	if(offsetList[j].dist >= 0.1)
         {
      	   if (data->animData[j].direction <= 0)
               offsetList[j].dir *= -1 / offsetList[j].dist;
            else
               offsetList[j].dir *= 1 / offsetList[j].dist;
         }
	   	clearAnimTransform();
         offsetList[j].hasOffset = true;
      }
      else
         offsetList[j].hasOffset = false;

		myThread->SetSequence(0);
   }
   if(currentAnimation != -1)
   {
      // it's a death animation: set it to the end
      myThread->SetSequence(animIndex[currentAnimation]);
   	if (data->animData[currentAnimation].direction > 0)
   		myThread->SetPosition (0.99f);
   	else
   		myThread->SetPosition (0);
      pickNewAnimation = false;
   }

   delete flameImage.shape;
   flameImage.shape = 0;
	flameThread = 0;

	if (isGhost()) {
		char name[256];
		strcpy(name, data->flameShapeName);
		strcat(name, ".dts");

		ResourceManager *rm = SimResource::get(manager);
		Resource<TSShape> shape = rm->load(name, true);
	   if(bool(shape))
	   {
	      flameImage.shape = new TSShapeInstance(shape, *rm);
         flameThread = flameImage.shape->CreateThread();
         flameThread->setTimeScale(1.0f);
         flameThread->SetSequence("activation");
	   }
	}
	
	// Container & Collision
	boundingBox.fMin.x = -data->boxWidth;
	boundingBox.fMin.y = -data->boxDepth;
	boundingBox.fMin.z = 0;
	boundingBox.fMax.x = data->boxWidth;
	boundingBox.fMax.y = data->boxDepth;
	boundingBox.fMax.z = data->boxNormalHeight;
	collisionImage.bbox.fMin = boundingBox.fMin;
	collisionImage.bbox.fMax = boundingBox.fMax;
	collisionImage.crouchBox.fMin = boundingBox.fMin;
	collisionImage.crouchBox.fMax = boundingBox.fMax;
	setBoundingBox ();
	collisionImage.sphere.radius = (collisionImage.bbox.fMax.z - collisionImage.bbox.fMin.z) / 2;
	collisionImage.sphere.center = Point3F(0.0f,0.0f, collisionImage.sphere.radius);
	collisionImage.shapeInst = image.shape;
	collisionImage.collisionDetail = 0;
	chaseNode = image.shape->getShape().findNode ("dummyalways chasecam");
	eyeNode = image.shape->getNodeAtCurrentDetail("dummy eye");

	// Resolve all the mount node indexes.
   for(i = 0; i < MaxMountPoints; i++) {
		image.shape->setDetailLevel(0);
      mountNode[i] = image.shape->getNodeAtCurrentDetail(NodeMountName[i]);

		// HACK Alert!
		// Lower detail nodes are patch to reference the same
		// transform as the highest detail.
		TS::ShapeInstance::NodeInstance *node = image.shape->getNode(mountNode[i]);
		for (int d = 1; d < image.shape->getShape().fDetails.size(); d++) {
			image.shape->setDetailLevel(d);
      	int dn = image.shape->getNodeAtCurrentDetail(NodeMountName[i]);
			if (dn != -1)
				image.shape->getNode(dn)->fpTransform = node->fpTransform;
		}
   }
   image.shape->setDetailLevel(0);

	// Update initial state of images transfered from the server.
	for (i = 0; i < MaxItemImages; i++) {
		ItemImageEntry& itemImage = itemImageList[i];
		if (itemImage.state == ItemImageEntry::Fire)
			setImageState(i,ItemImageEntry::Fire);
	}

   return true;
}