Game Development Community

Footpuff and vehicle dust fix for TGEA 1.7.1

by Konrad Kiss · 08/04/2008 (12:48 pm) · 8 comments

Inspired by Anthony Rosenbaum's Plastic Gem #34: TGEA Decals resource, and finally leaving footprints, I tried to get footpuffs and vehicle puffs back into TGEA.

Before you start, please check out my Automatic blended terrain texture property map generation resource, because you will need property maps set up to see the puffs.

Ok, first of all, open up T3D/player.cpp, and add this include after the rest of the includes:

#include "materials/materialPropertyMap.h"

Within the function Player::updateActionThread find the following code part that has been commented out:

//TerrainBlock* tBlock = static_cast<TerrainBlock*>(rInfo.object);

               // Footpuffs, if we can get the material color...
               /*S32 mapIndex = tBlock->mMPMIndex[0];
               if (mapIndex != -1) {

                 .... stuff ....

               }*/

and replace it with this:

TerrainBlock* tBlock = static_cast<TerrainBlock*>(rInfo.object);

               // Footpuffs, if we can get the material color...
               S32 mapIndex = tBlock->mMPMIndex[0];
               if (mapIndex != -1) {

                  MaterialPropertyMap* pMatMap = MaterialPropertyMap::get();
                  const MaterialPropertyMap::MapEntry* pEntry = pMatMap->getMapEntryFromIndex(mapIndex);
                  if(pEntry)
                  {
                     sound = pEntry->sound;
                     if( rInfo.t <= 0.5 && mWaterCoverage == 0.0f)
                     {
                        // New emitter every time for visibility reasons
                        ParticleEmitter * emitter = new ParticleEmitter;
                        emitter->onNewDataBlock( mDataBlock->footPuffEmitter );

			ColorF colorList[ParticleData::PDC_NUM_KEYS];

			for (S32 x = 0; x < 2; ++x)
				colorList[x].set(pEntry->puffColor[x].red,
					pEntry->puffColor[x].green,
					pEntry->puffColor[x].blue,
					pEntry->puffColor[x].alpha);

			for(S32 x = 2; x < ParticleData::PDC_NUM_KEYS; ++x)
				colorList[x].set( 1.0, 1.0, 1.0, 0.0 );

			emitter->setColors( colorList );

                        if( !emitter->registerObject() )
                        {
                           Con::warnf( ConsoleLogEntry::General, "Could not register emitter for particle of class: %s", mDataBlock->getName() );
                           delete emitter;
                           emitter = NULL;
                        }
                        else
                        {
                           emitter->emitParticles( pos, Point3F( 0.0, 0.0, 1.0 ), mDataBlock->footPuffRadius,
                                                   Point3F(0, 0, 0), mDataBlock->footPuffNumParts );
                           emitter->deleteWhenEmpty();
                        }
                     }
                  }
               }

Port info: ParticleEngine::PC_COLOR_KEYS became ParticleData::PDC_NUM_KEYS

If you would not have the property map for all the textures used in your map, then mapIndex would always be -1, and so the whole emitting would never happen. This is why you need the property maps set up for all the terrain textures.

A good idea would be to use a default color if no property map is defined, but since the property map is also used elsewhere, it is probably better, that this does not handle defaults here.

Anyway, the following changes in terrain/terrData.h and terrain/terrData.cpp are needed to fix vehicle tire dust puffs.

Open terrain/terrData.h, find the following declaration:

S32 mMPMIndex[10];

and replace it with this one for stability:

S32 mMPMIndex[TerrainBlock::MaterialGroups];

In terrain/terrData.cpp add the following include:

#include "materials/materialPropertyMap.h"

Within the TerrainBlock::onAdd() method, find the call addToScene(); (almost at the end of the method) and after this, insert the following:

MaterialPropertyMap* pMatMap = MaterialPropertyMap::get();
   for (int i = 0; i < TerrainBlock::MaterialGroups; i++)
   {                        
      StringTableEntry fn = mMaterialFileName[ i ];
      if (fn != NULL)
      {   
			char nameBuff[512];
			dStrcpy(nameBuff, mTerrFileName);
			const char *p = dStrrchr(fn, '/');
			if(p) p++;
			else p = nameBuff;

			mMPMIndex[ i ] = pMatMap->getIndexFromName( p );
      }
      else mMPMIndex[ i ] = -1;
   }

This sets up the mMPMIndex array using the property map indices of each texture used.

Ok, let's go on. While testing, I came across a weird problem. The puffs wouldn't emit on textures that had their extensions within the name. To fix that, we need to strip the extensions when the property map names are checked against to get an id (getIndexFromName). We could do this in terrData.cpp as well, but I chose to do it in the function instead, just in case it is used somewhere else as well...

Open materials/materialPropertyMap.cpp and add the following includes:

#include "core/frameAllocator.h"
#include "platformWin32/platformWin32.h"

Then replace the MaterialPropertyMap::getIndexFromName method with the following code:

S32 MaterialPropertyMap::getIndexFromName(StringTableEntry name) const
{
   S32 pathLen = dStrlen( name );
   FrameTemp<char> szPathCopy( pathLen + 1);

   dStrcpy( szPathCopy, name );
   forwardslash( szPathCopy );

   const char *path = dStrrchr(szPathCopy, '/');
   if(!path)
      path = szPathCopy;
   else
      path++;
   char *namebase = Con::getReturnBuffer(dStrlen(path) + 1);
   dStrcpy(namebase, path);
   char *ext = dStrrchr(namebase, '.');
   if(ext)
      *ext = 0;

   S32 ret = -1;
   for (U32 i = 0; i < mMapEntries.size(); i++) {
      if (dStricmp(mMapEntries[ i ].name, namebase) == 0) {
         ret = i;
         break;
      }
   }
   return ret;
}

This strips the filename of the path and extension - a'la the FileBase console function, and so it finds the property map by the texture name even if it has the extension specified.

That's all, have fun!

About the author

Lead Developer at Bitgap Games (www.bitgap.com) currently working on Xenocell (www.xenocell.com) a massively multiplayer action strategy game based on Torque 3D technology.


#1
08/04/2008 (1:04 pm)
Heh thanks for the shout out, I was thinking of fixing this too, glad I inspired you to do it!
#2
08/04/2008 (2:00 pm)
Just doing my part for all the gems. :)
#3
08/04/2008 (10:58 pm)
Nice, thanks for posting that. I tried it myself about a month ago with no success, but your code worked perfectly out of the box.
#4
08/04/2008 (11:21 pm)
That's good to hear, I was worried I might have forgotten something.
#5
08/05/2008 (7:48 pm)
Now that's just magical...!

One odd thing happened... at first, I wasn't getting foot puffs, checked the console, and it told me I wasn't getting the correct include path for the propertyMap.cs--I'd called it propertyMaps.cs. However, the sound was much louder than it usually is (to the point where it was audible lol). When I fixed the pathname, the foot puffs showed up, but the footsteps became muted again.

Thank you Mr. Kiss!
#6
12/19/2008 (11:13 am)
bit of a bump,
but how to get the footpuffs less blocky?
they render as squares, would be nice to have them as dusty type particles.
any ideas?
#7
12/19/2008 (11:18 am)
Weird, I had no such problem in 1.7.1. Haven't checked in 1.8 yet. Are you sure that you have the right particle texture set for the puff? If you use your own particle bitmap, try the one that comes with the engine, see if that helps.
#8
12/19/2008 (1:42 pm)
mmm, in the player.cs, the "LightPuff" particedata has no textureName defined by default. I added one, it now works a treat.
dunno how I missed that...