Increase the number of animations per character
by Orion Elenzil · 01/18/2006 (5:19 pm) · 7 comments
This resource is very heavily based on Chris Calef's and other's discussion here.
It should have slightly better performance than the code there however,
because it strips off the file extension and the sequence name as well.
Motivation:
TGE 1.3 has a limit to the number of animations you can have per character.
The limit stems from the fact that the Names of the animation sequences must all be sent from serve to client in one buffer of about 1500 bytes.
I hear that TGE 1.4 takes care of this.
In our case, we've got about 100 animations which fall under this modification,
and by using this mod our byte-stream needs are reduced from about 60 bytes per animation to about 10,
allowing us to fit well within 1500-byte limit.
The sequences come from the player.cs file which is typically next to player.dts.
A typical sequence definition from that file looks something like this:
Before sending it over the wire, the engine expands "./jump_around.dsq jump_around" into something like "starter.fps/data/shapes/characters/jump_around.dsq jump_around".
This resource handles the (for us) very common situation where:
1. the animation file is a sibling of the .dts file
2. the animation file has the extension ".dsq".
3. the filename of the .dsq is the same as the name as the animation.
- this third item might not be common for everyone, but basically i highly recommend making it so if you're running into this issue.
If all three of these criteria are met then a flag is set in the bitstream to indicate it, and only the name of the animation is sent.
so instead of "starter.fps/data/shapes/characters/jump_around.dsq jump_around", we just send "jump_around".
Since a 1-bit flag is inserted in the bitstream to indicate whether this compression has been done or not,
this mod is backwards compatible with standard sequence names & locations.
tsShapeConstruct.cc
Basically packData() and unpackData() are rewritten.
Don't forget to add 'stockExtn' in front of packData().
It should have slightly better performance than the code there however,
because it strips off the file extension and the sequence name as well.
Motivation:
TGE 1.3 has a limit to the number of animations you can have per character.
The limit stems from the fact that the Names of the animation sequences must all be sent from serve to client in one buffer of about 1500 bytes.
I hear that TGE 1.4 takes care of this.
In our case, we've got about 100 animations which fall under this modification,
and by using this mod our byte-stream needs are reduced from about 60 bytes per animation to about 10,
allowing us to fit well within 1500-byte limit.
The sequences come from the player.cs file which is typically next to player.dts.
A typical sequence definition from that file looks something like this:
sequence28 = "./jump_around.dsq jump_around";
Before sending it over the wire, the engine expands "./jump_around.dsq jump_around" into something like "starter.fps/data/shapes/characters/jump_around.dsq jump_around".
This resource handles the (for us) very common situation where:
1. the animation file is a sibling of the .dts file
2. the animation file has the extension ".dsq".
3. the filename of the .dsq is the same as the name as the animation.
- this third item might not be common for everyone, but basically i highly recommend making it so if you're running into this issue.
If all three of these criteria are met then a flag is set in the bitstream to indicate it, and only the name of the animation is sent.
so instead of "starter.fps/data/shapes/characters/jump_around.dsq jump_around", we just send "jump_around".
Since a 1-bit flag is inserted in the bitstream to indicate whether this compression has been done or not,
this mod is backwards compatible with standard sequence names & locations.
tsShapeConstruct.cc
Basically packData() and unpackData() are rewritten.
Don't forget to add 'stockExtn' in front of packData().
[b]static const char* stockExtn = ".dsq";[/b]
void TSShapeConstructor::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeString(mShape);
S32 count = 0;
for (S32 b=0; b<MaxSequences; b++)
if (mSequence[b])
count++;
stream->writeInt(count,NumSequenceBits);
char stockPath[256];
S32 stockPathLen;
char pathBuf[256];
char nameBuf[64];
char* cp;
bool isStockPath;
bool isStockExtn;
bool isStockName;
dStrcpy(stockPath, mShape);
cp = dStrrchr(stockPath, '/');
if (cp)
*(cp+1) = '[[60c1cee7d7e72]]';
stockPathLen = dStrlen(stockPath);
for (S32 i=0; i<MaxSequences; i++) {
if (mSequence[i]) {
dStrcpy(pathBuf, mSequence[i]);
cp = dStrrchr(pathBuf, ' ');
isStockPath = isStockExtn = isStockName = false;
if (cp) {
*cp = '[[60c1cee7d7e72]]';
dStrcpy(nameBuf, cp + 1);
isStockPath = !dStrnicmp(stockPath, pathBuf, stockPathLen);
cp = dStrrchr(pathBuf, '.');
if (cp) {
isStockExtn = !dStricmp (cp, stockExtn);
if (isStockExtn) {
*cp = '[[60c1cee7d7e72]]';
isStockName = !dStricmp(nameBuf, pathBuf + stockPathLen);
}
}
}
if (stream->writeFlag(isStockPath && isStockExtn && isStockName))
stream->writeString(nameBuf);
else
stream->writeString(mSequence[i]);
}
}
}
void TSShapeConstructor::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
mShape = stream->readSTString();
bool isStock;
char stockPath[256];
char pathBuf [256];
char* cp;
dStrcpy(stockPath, mShape);
cp = dStrrchr(stockPath, '/');
if (cp)
*(cp+1) = '[[60c1cee7d7e72]]';
S32 i = 0, count = stream->readInt(NumSequenceBits);
for (; i<count; i++) {
isStock = stream->readFlag();
mSequence[i] = stream->readSTString();
if (isStock) {
dSprintf(pathBuf, sizeof(pathBuf), "%s%s%s %s", stockPath, mSequence[i], stockExtn, mSequence[i]);
mSequence[i] = StringTable->insert(pathBuf);
}
}
while (i<MaxSequences)
mSequence[i++] = NULL;
}About the author
#2
how do you trigger the one you want ?
- by just knowing the cut-points, or something nicer ?
01/21/2006 (12:06 pm)
i didn't realize you can put multiple animations in a single .dsq.how do you trigger the one you want ?
- by just knowing the cut-points, or something nicer ?
#3
01/23/2006 (9:18 pm)
did 1.4 fix this issue? or is it still an issue?
#5
03/09/2006 (10:34 pm)
Orion, to answer yuor question about how you trigger the one you want, you just use the name of the sequence helper you used in Max, Maya or whatever. The sequence helper itself marks the begin and end times, so you don't have to know about them later. You basically just make one long timeline with a bunch of different sequence helpers pointing to various time segments then export it to a single dsq.
#6
My characters have many attack animations, I want what they random this animations.
04/21/2006 (9:25 am)
How I play one animation in my characters? My characters have many attack animations, I want what they random this animations.
#7
01/31/2007 (6:37 am)
Hi, warning about the built-in 1.4 fix. After defining TS_IS_RELATIVE_SEQUENCES i'm getting a crash upon mission load: Run-Time Check Failure #2 - Stack around the variable 'pathedSeq' was corrupted. This is happening in debug mode. Do not know about release. 
Torque Owner Josh Moore
In Player.h, find:
And set it to a higher number; we have ours set at 512.