Example #1
0
void ForestConvex::getPolyList(AbstractPolyList* list)
{
   list->setTransform( &mTransform, Point3F(mScale,mScale,mScale));
   list->setObject(mObject);

   TSShapeInstance *si = mData->getShapeInstance();

   S32 detail = mData->getCollisionDetails()[hullId];
   si->animate(detail);
   si->buildPolyList(list, detail);
}
Example #2
0
void ForestConvex::getFeatures( const MatrixF &mat, const VectorF &n, ConvexFeature *cf )
{
   cf->material = 0;
   cf->object = mObject;

   TSShapeInstance *si = mData->getShapeInstance();

   TSShape::ConvexHullAccelerator* pAccel =
      si->getShape()->getAccelerator(mData->getCollisionDetails()[hullId]);
   AssertFatal(pAccel != NULL, "Error, no accel!");

   F32 currMaxDP = mDot(pAccel->vertexList[0], n);
   U32 index = 0;
   U32 i;
   for (i = 1; i < pAccel->numVerts; i++) 
   {
      F32 dp = mDot(pAccel->vertexList[i], n);
      if (dp > currMaxDP) 
      {
         currMaxDP = dp;
         index = i;
      }
   }

   const U8* emitString = pAccel->emitStrings[index];
   U32 currPos = 0;
   U32 numVerts = emitString[currPos++];
   for (i = 0; i < numVerts; i++) 
   {
      cf->mVertexList.increment();
      U32 index = emitString[currPos++];
      mat.mulP(pAccel->vertexList[index], &cf->mVertexList.last());
   }

   U32 numEdges = emitString[currPos++];
   for (i = 0; i < numEdges; i++) 
   {
      U32 ev0 = emitString[currPos++];
      U32 ev1 = emitString[currPos++];
      cf->mEdgeList.increment();
      cf->mEdgeList.last().vertex[0] = ev0;
      cf->mEdgeList.last().vertex[1] = ev1;
   }

   U32 numFaces = emitString[currPos++];
   for (i = 0; i < numFaces; i++) 
   {
      cf->mFaceList.increment();
      U32 plane = emitString[currPos++];
      mat.mulV(pAccel->normalList[plane], &cf->mFaceList.last().normal);
      for (U32 j = 0; j < 3; j++)
         cf->mFaceList.last().vertex[j] = emitString[currPos++];
   }
}
Example #3
0
bool FlyingVehicleData::preload(bool server, String &errorStr)
{
   if (!Parent::preload(server, errorStr))
      return false;

   TSShapeInstance* si = new TSShapeInstance(mShape, false);

   // Resolve objects transmitted from server
   if (!server) {
      for (S32 i = 0; i < MaxSounds; i++)
         if (sound[i])
            Sim::findObject(SimObjectId(sound[i]),sound[i]);

      for (S32 j = 0; j < MaxJetEmitters; j++)
         if (jetEmitter[j])
            Sim::findObject(SimObjectId(jetEmitter[j]),jetEmitter[j]);
   }

   // Extract collision planes from shape collision detail level
   if (collisionDetails[0] != -1)
   {
      MatrixF imat(1);
      PlaneExtractorPolyList polyList;
      polyList.mPlaneList = &rigidBody.mPlaneList;
      polyList.setTransform(&imat, Point3F(1,1,1));
      si->animate(collisionDetails[0]);
      si->buildPolyList(&polyList,collisionDetails[0]);
   }

   // Resolve jet nodes
   for (S32 j = 0; j < MaxJetNodes; j++)
      jetNode[j] = mShape->findNode(sJetNode[j]);

   //
   maxSpeed = maneuveringForce / minDrag;

   delete si;
   return true;
}
Example #4
0
Point3F ForestConvex::support(const VectorF& v) const
{
   TSShapeInstance *si = mData->getShapeInstance();

   TSShape::ConvexHullAccelerator* pAccel =
      si->getShape()->getAccelerator(mData->getCollisionDetails()[hullId]);
   AssertFatal(pAccel != NULL, "Error, no accel!");

   F32 currMaxDP = mDot(pAccel->vertexList[0], v);
   U32 index = 0;
   for (U32 i = 1; i < pAccel->numVerts; i++) 
   {
      F32 dp = mDot(pAccel->vertexList[i], v);
      if (dp > currMaxDP) 
      {
         currMaxDP = dp;
         index = i;
      }
   }

   return pAccel->vertexList[index];
}
Example #5
0
bool ForestItem::buildPolyList( AbstractPolyList* polyList, const Box3F &box, const SphereF &sphere ) const
{
   TSForestItemData *data = (TSForestItemData*)mDataBlock;
   
   bool ret = false;

   MatrixF xfm = getTransform();
   polyList->setTransform( &xfm, Point3F(mScale,mScale,mScale) );

   TSShapeInstance *si = data->getShapeInstance();

   const Vector<S32> &details = data->getCollisionDetails();
   S32 detail;
   for  (U32 i = 0; i < details.size(); i++ ) 
   {
      detail = details[i];
      if (detail != -1) 
         ret |= si->buildPolyList( polyList, detail );         
   }

   return ret;   
}
Example #6
0
void Turret::getNodeOffset (TMat3F *trans, char *nodeName, int Node)
{
	TSShapeInstance *si = image.shape;

	if(si)
	   {
	      int node;

			if (Node == -1)
				node = si->getShape().findNode(nodeName);
			else
				node = Node;

			if (node != -1)
				{
					TMat3F nodeTrans;
					nodeTrans.identity();
					nodeTrans.p = si->getTransform (node).p;
					m_mul (nodeTrans, getTransform(), trans);
				}
	   }
}
void TSLastDetail::_update()
{
   // We're gonna render... make sure we can.
   bool sceneBegun = GFX->canCurrentlyRender();
   if ( !sceneBegun )
      GFX->beginScene();

   _validateDim();

   Vector<GBitmap*> bitmaps;
   Vector<GBitmap*> normalmaps;

   // We need to create our own instance to render with.
   TSShapeInstance *shape = new TSShapeInstance( mShape, true );

   // Animate the shape once.
   shape->animate( mDl );

   // So we don't have to change it everywhere.
   const GFXFormat format = GFXFormatR8G8B8A8;  

   S32 imposterCount = ( ((2*mNumPolarSteps) + 1 ) * mNumEquatorSteps ) + ( mIncludePoles ? 2 : 0 );

   // Figure out the optimal texture size.
   Point2I texSize( smMaxTexSize, smMaxTexSize );
   while ( true )
   {
      Point2I halfSize( texSize.x / 2, texSize.y / 2 );
      U32 count = ( halfSize.x / mDim ) * ( halfSize.y / mDim );
      if ( count < imposterCount )
      {
         // Try half of the height.
         count = ( texSize.x / mDim ) * ( halfSize.y / mDim );
         if ( count >= imposterCount )
            texSize.y = halfSize.y;
         break;
      }

      texSize = halfSize;
   }

   GBitmap *imposter = NULL;
   GBitmap *normalmap = NULL;
   GBitmap destBmp( texSize.x, texSize.y, true, format );
   GBitmap destNormal( texSize.x, texSize.y, true, format );

   U32 mipLevels = destBmp.getNumMipLevels();

   ImposterCapture *imposterCap = new ImposterCapture();

   F32 equatorStepSize = M_2PI_F / (F32)mNumEquatorSteps;

   static const MatrixF topXfm( EulerF( -M_PI_F / 2.0f, 0, 0 ) );
   static const MatrixF bottomXfm( EulerF( M_PI_F / 2.0f, 0, 0 ) );

   MatrixF angMat;

   F32 polarStepSize = 0.0f;
   if ( mNumPolarSteps > 0 )
      polarStepSize = -( 0.5f * M_PI_F - mDegToRad( mPolarAngle ) ) / (F32)mNumPolarSteps;

   PROFILE_START(TSLastDetail_snapshots);

   S32 currDim = mDim;
   for ( S32 mip = 0; mip < mipLevels; mip++ )
   {
      if ( currDim < 1 )
         currDim = 1;
      
      dMemset( destBmp.getWritableBits(mip), 0, destBmp.getWidth(mip) * destBmp.getHeight(mip) * GFXFormat_getByteSize( format ) );
      dMemset( destNormal.getWritableBits(mip), 0, destNormal.getWidth(mip) * destNormal.getHeight(mip) * GFXFormat_getByteSize( format ) );

      bitmaps.clear();
      normalmaps.clear();

      F32 rotX = 0.0f;
      if ( mNumPolarSteps > 0 )
         rotX = -( mDegToRad( mPolarAngle ) - 0.5f * M_PI_F );

      // We capture the images in a particular order which must
      // match the order expected by the imposter renderer.

      imposterCap->begin( shape, mDl, currDim, mRadius, mCenter );

      for ( U32 j=0; j < (2 * mNumPolarSteps + 1); j++ )
      {
         F32 rotZ = -M_PI_F / 2.0f;

         for ( U32 k=0; k < mNumEquatorSteps; k++ )
         {            
            angMat.mul( MatrixF( EulerF( rotX, 0, 0 ) ),
                        MatrixF( EulerF( 0, 0, rotZ ) ) );

            imposterCap->capture( angMat, &imposter, &normalmap );

            bitmaps.push_back( imposter );
            normalmaps.push_back( normalmap );

            rotZ += equatorStepSize;
         }

         rotX += polarStepSize;

         if ( mIncludePoles )
         {
            imposterCap->capture( topXfm, &imposter, &normalmap );

            bitmaps.push_back(imposter);
            normalmaps.push_back( normalmap );

            imposterCap->capture( bottomXfm, &imposter, &normalmap );

            bitmaps.push_back( imposter );
            normalmaps.push_back( normalmap );
         }         
      }

      imposterCap->end();

      Point2I texSize( destBmp.getWidth(mip), destBmp.getHeight(mip) );

      // Ok... pack in bitmaps till we run out.
      for ( S32 y=0; y+currDim <= texSize.y; )
      {
         for ( S32 x=0; x+currDim <= texSize.x; )
         {
            // Copy the next bitmap to the dest texture.
            GBitmap* bmp = bitmaps.first();
            bitmaps.pop_front();
            destBmp.copyRect( bmp, RectI( 0, 0, currDim, currDim ), Point2I( x, y ), 0, mip );
            delete bmp;

            // Copy the next normal to the dest texture.
            GBitmap* normalmap = normalmaps.first();
            normalmaps.pop_front();
            destNormal.copyRect( normalmap, RectI( 0, 0, currDim, currDim ), Point2I( x, y ), 0, mip );
            delete normalmap;

            // Did we finish?
            if ( bitmaps.empty() )
               break;

            x += currDim;
         }

         // Did we finish?
         if ( bitmaps.empty() )
            break;

         y += currDim;
      }

      // Next mip...
      currDim /= 2;
   }

   PROFILE_END(); // TSLastDetail_snapshots

   delete imposterCap;
   delete shape;   
   
   
   // Should we dump the images?
   if ( Con::getBoolVariable( "$TSLastDetail::dumpImposters", false ) )
   {
      String imposterPath = mCachePath + ".imposter.png";
      String normalsPath = mCachePath + ".imposter_normals.png";

      FileStream stream;
      if ( stream.open( imposterPath, Torque::FS::File::Write  ) )
         destBmp.writeBitmap( "png", stream );
      stream.close();

      if ( stream.open( normalsPath, Torque::FS::File::Write ) )
         destNormal.writeBitmap( "png", stream );
      stream.close();
   }

   // DEBUG: Some code to force usage of a test image.
   //GBitmap* tempMap = GBitmap::load( "./forest/data/test1234.png" );
   //tempMap->extrudeMipLevels();
   //mTexture.set( tempMap, &GFXDefaultStaticDiffuseProfile, false );
   //delete tempMap;

   DDSFile *ddsDest = DDSFile::createDDSFileFromGBitmap( &destBmp );
   DDSUtil::squishDDS( ddsDest, GFXFormatDXT3 );

   DDSFile *ddsNormals = DDSFile::createDDSFileFromGBitmap( &destNormal );
   DDSUtil::squishDDS( ddsNormals, GFXFormatDXT5 );

   // Finally save the imposters to disk.
   FileStream fs;
   if ( fs.open( _getDiffuseMapPath(), Torque::FS::File::Write ) )
   {
      ddsDest->write( fs );
      fs.close();
   }
   if ( fs.open( _getNormalMapPath(), Torque::FS::File::Write ) )
   {
      ddsNormals->write( fs );
      fs.close();
   }

   delete ddsDest;
   delete ddsNormals;

   // If we did a begin then end it now.
   if ( !sceneBegun )
      GFX->endScene();
}
Example #8
0
bool ForestItem::castRay( const Point3F &start, const Point3F &end, RayInfo *outInfo, bool rendered ) const
{
   if ( !mWorldBox.collideLine( start, end ) )
      return false;

   Point3F s, e;
   MatrixF mat = getTransform();
   mat.scale( Point3F(mScale) );
   mat.inverse();

   mat.mulP( start, &s );
   mat.mulP( end, &e );

   TSForestItemData *data = (TSForestItemData*)mDataBlock;
   TSShapeInstance *si = data->getShapeInstance();

   if ( !si ) 
      return false;
   
   if ( rendered )
   {
      // Always raycast against detail level zero
      // because it makes lots of things easier.
      if ( !si->castRayRendered( s, e, outInfo, 0 ) )
         return false;

      if ( outInfo->userData != NULL )
         *(ForestItem*)(outInfo->userData) = *this;

      return true;
   }

   RayInfo shortest;  
   shortest.t = 1e8;
   bool gotMatch = false;
   S32 detail;

   const Vector<S32> &details = data->getLOSDetails();
   for (U32 i = 0; i < details.size(); i++) 
   {
      detail = details[i];
      if (detail != -1) 
      {
         //si->animate(data->mLOSDetails[i]);

         if ( si->castRayOpcode( detail, s, e, outInfo ) )         
         {
            if (outInfo->t < shortest.t)
            {
               gotMatch = true;
               shortest = *outInfo;      
            }
         }
      }
   }

   if ( !gotMatch )
      return false;

   // Copy out the shortest time...
   *outInfo = shortest;

   if ( outInfo->userData != NULL )
      *(ForestItem*)(outInfo->userData) = *this;

   return true;   
}