Random fxShapeReplicator
by Dave Young · in Torque Game Engine · 04/12/2006 (1:17 pm) · 8 replies
Has anyone seen a version of fxShapeReplicator that will place a random shape from among a list of shapes?
Say you had 5 different pine tree models, you could pix 5 models from a list and the replicator would choose randomly as it is placing them.
Is this something that has been done before already?
Say you had 5 different pine tree models, you could pix 5 models from a list and the replicator would choose randomly as it is placing them.
Is this something that has been done before already?
#2
That would be an excellent resource for TGE as well. Any reason it would not work in TGE that you know of?
04/13/2006 (8:34 am)
Dave, Fantastic!That would be an excellent resource for TGE as well. Any reason it would not work in TGE that you know of?
#3
04/13/2006 (8:50 am)
No reason. the changes I made were extremely elementary, did not involve graphic updates or anything. I will port to TGE later and make a resource out of it.
#4
04/13/2006 (9:24 am)
Dave, Excellent, that would be a really useful contribution to the community.
#5
First, in fxShapeReplicator.h:
Pretty simple, just make an array for the shape names, and set the defaults. I set the default string to "N/A" because for some reason when I left it at "" it would not write the fields to the mission file (unless I populate them with shape paths).
Then fxShapeReplicator.cc:
further down...
That's it, should compile fine, but the biggest problem is that I have to fill all 16 of the slots. I picked 16 because in the sharp tree pack there are sometimes 15 or so varieties of trees, and that makes a much more interesting forest...
I hope that you (Dave) or anyone else can help with this, I think that it'll be a great resource (maybe do it to the foliage replicator too)
04/13/2006 (8:04 pm)
Oddly enough I had already started working on the same resource. I was planning to add 16 shapes to my replicator. I am having some problems with it though that perhaps you can shed some light on. I've made my changes to TLK1.4 although I don't see why it would be different for straight TGE (I don't mess with any TLK code). I'll post my changes so maybe I can get some help with this:First, in fxShapeReplicator.h:
// Field Data.
class tagFieldData
{
public:
U32 mSeed;
//BS: changed to array of shapes
StringTableEntry mShapeFile[16];
//END
U32 mShapeCount;further down...tagFieldData()
{
// Set Defaults.
mSeed = 1376312589;
//BS: set default for each shape
for(int i=0;i<16;i++)
{
mShapeFile[i] = StringTable->insert("N/A");
}
//END
mShapeCount = 10;Pretty simple, just make an array for the shape names, and set the defaults. I set the default string to "N/A" because for some reason when I left it at "" it would not write the fields to the mission file (unless I populate them with shape paths).
Then fxShapeReplicator.cc:
addGroup( "Media" );
addField( "ShapeFile1", TypeFilename, Offset( mFieldData.mShapeFile[0], fxShapeReplicator ) );
addField( "ShapeFile2", TypeFilename, Offset( mFieldData.mShapeFile[1], fxShapeReplicator ) );
addField( "ShapeFile3", TypeFilename, Offset( mFieldData.mShapeFile[2], fxShapeReplicator ) );
addField( "ShapeFile4", TypeFilename, Offset( mFieldData.mShapeFile[3], fxShapeReplicator ) );
addField( "ShapeFile5", TypeFilename, Offset( mFieldData.mShapeFile[4], fxShapeReplicator ) );
addField( "ShapeFile6", TypeFilename, Offset( mFieldData.mShapeFile[5], fxShapeReplicator ) );
addField( "ShapeFile7", TypeFilename, Offset( mFieldData.mShapeFile[6], fxShapeReplicator ) );
addField( "ShapeFile8", TypeFilename, Offset( mFieldData.mShapeFile[7], fxShapeReplicator ) );
addField( "ShapeFile9", TypeFilename, Offset( mFieldData.mShapeFile[8], fxShapeReplicator ) );
addField( "ShapeFile10", TypeFilename, Offset( mFieldData.mShapeFile[9], fxShapeReplicator ) );
addField( "ShapeFile11", TypeFilename, Offset( mFieldData.mShapeFile[10], fxShapeReplicator ) );
addField( "ShapeFile12", TypeFilename, Offset( mFieldData.mShapeFile[11], fxShapeReplicator ) );
addField( "ShapeFile13", TypeFilename, Offset( mFieldData.mShapeFile[12], fxShapeReplicator ) );
addField( "ShapeFile14", TypeFilename, Offset( mFieldData.mShapeFile[13], fxShapeReplicator ) );
addField( "ShapeFile15", TypeFilename, Offset( mFieldData.mShapeFile[14], fxShapeReplicator ) );
addField( "ShapeFile16", TypeFilename, Offset( mFieldData.mShapeFile[15], fxShapeReplicator ) );
endGroup( "Media" );I'll mention that I tried to use a for loop on that one, but I couldn't get that to work either so I had to type out all 16...void fxShapeReplicator::CreateShapes(void)
{
F32 HypX, HypY;
F32 Angle;
U32 RelocationRetry;
Point3F ShapePosition;
Point3F ShapeStart;
Point3F ShapeEnd;
Point3F ShapeScale;
EulerF ShapeRotation;
QuatF QRotation;
bool CollisionResult;
RayInfo RayEvent;
TSShape* pShape;
Container* pContainer;
//BS: added 3 variables
bool bValid = false;
MRandomLCG randomIndex;
S32 pickIndex = 0;
//ENDfurther down...// Cannot continue without shapes!
for(int i=0;i<16;i++)
{
if(mFieldData.mShapeFile[i] != "" && mFieldData.mShapeFile[i] != "N/A")
{
bValid = true;
break;
}
}
// cannot continue with no shapes!
if (!bValid) return;There I just check if at least one of the shapes has a shape path in it to continue..// pick a random shape index
randomIndex.setSeed(RandomGen.randI(0,mFieldData.mSeed));
pickIndex = randomIndex.randI(0,15);
do
{
pickIndex = randomIndex.randI(0,15);
Con::warnf(ConsoleLogEntry::General, "[%d] - was picked!", pickIndex);
}while(mFieldData.mShapeFile[pickIndex] == "N/A" || mFieldData.mShapeFile[pickIndex] == "");
// Set the 'shapeName' field.
fxStatic->setField("shapeName", mFieldData.mShapeFile[pickIndex]);Now, here is a major trouble spot, this is *supposed* to keep getting a random index until it hits a valid shape. It doesn't and I can't figure out why, unless I have ALL of my 16 shapes filled out, it won't work. (works great if I do hehe)further down...
// Write Replication Flag.
if (stream->writeFlag(mask & ReplicationMask))
{
stream->writeAffineTransform(mObjToWorld); // Replicator Position.
stream->writeInt(mFieldData.mSeed, 32); // Replicator Seed.
stream->writeInt(mFieldData.mShapeCount, 32); // Shapes Count.
stream->writeInt(mFieldData.mShapeRetries, 32); // Shapes Retries.
//BS: changed to array
for(int i=0;i<16;i++)
{
stream->writeString(mFieldData.mShapeFile[i]);
}
//ENDand then...// Read Replication Details.
if(stream->readFlag())
{
MatrixF ReplicatorObjectMatrix;
stream->readAffineTransform(&ReplicatorObjectMatrix); // Replication Position.
mFieldData.mSeed = stream->readInt(32); // Replicator Seed.
mFieldData.mShapeCount = stream->readInt(32); // Shapes Count.
mFieldData.mShapeRetries = stream->readInt(32); // Shapes Retries.
//BS: changed to array
for(int i=0;i<16;i++)
{
mFieldData.mShapeFile[i] = stream->readSTString(); // Shape File.
}
//ENDThat's it, should compile fine, but the biggest problem is that I have to fill all 16 of the slots. I picked 16 because in the sharp tree pack there are sometimes 15 or so varieties of trees, and that makes a much more interesting forest...
I hope that you (Dave) or anyone else can help with this, I think that it'll be a great resource (maybe do it to the foliage replicator too)
#6
04/13/2006 (8:07 pm)
Dave, you should post a TSE resource. I'd find this handy.
#7
That way, *any* random number in the range will work, returning a valid shape.
Our implementations are very similar. You posted the code first, so why don't you go ahead and finish it up as a resource!
04/14/2006 (2:32 am)
Ben, what I did to help the problem was to keep the checks for shapeFile[1] that are in CreateShape. If that was empty I return. This means that only the first shape must be filled. Then, if any others are empty, I fill it with the contents of shapeFile[1]. I did this before the call to CreateShapes, eliminating the need for a do->while loop. Because this loop runs for each shape in the replicator, I decided to take it out to speed up the replicator. Making the shapefilename validation and substitutions before this point helped considerably.That way, *any* random number in the range will work, returning a valid shape.
Our implementations are very similar. You posted the code first, so why don't you go ahead and finish it up as a resource!
#8
Anyway, your suggestions did help me to clean up the code a bit. I went ahead and made a resource out of it, so when that gets approved it should be up!
04/14/2006 (7:09 pm)
Thanks a lot for the help, it turns out I needed to set the mShapeFile to NULL instead of using the StringTable->insert(""); ... odd that the replicator worked fine with one variable set to that... Anyway, your suggestions did help me to clean up the code a bit. I went ahead and made a resource out of it, so when that gets approved it should be up!
Torque 3D Owner Dave Young
Dave Young Games