Game Development Community

Datablock pack/unpack problems

by Ian Omroth Hardingham · in Torque Game Engine · 11/25/2003 (12:27 pm) · 7 replies

Hello,
(apologies in advance for the long post)
I have a problem. I added some variables to the PlayerData datablock:

struct PlayerData: public ShapeBaseData
{
   ...
   F32 axisUpperLimit[MAX_AXES];
   F32 axisLowerLimit[MAX_AXES];
   ...

And then added them to packdata

void PlayerData::packData(BitStream* stream)
{
...
      for (i = 0; i < 3; i ++)
   {
      stream->writeFloat(axisLowerLimit[i], 8);
      stream->writeFloat(axisUpperLimit[i], 8);
      
      Con::printf("outgoing");
      Con::printf("%d : %f %f\n", i, axisLowerLimit[i], axisUpperLimit[i]);
   }

and added them to unpackdata :)

void PlayerData::unpackData(BitStream* stream)
...
for (i=0; i < 3; i ++)
   {
      axisLowerLimit[i] = stream->readFloat(8);
      axisUpperLimit[i] = stream->readFloat(8);

      Con::printf("incoming");
      Con::printf("%d : %f %f\n", i, axisLowerLimit[i], axisUpperLimit[i]);
   }

(the printfs are for debugging)

Now, unfortunately the variables are not being transmitted properly. During load, the printfs print the first 3 of my variables. In my definition of the datablock in player.cs these are set to be:
AxisLowerLimit[0] = 5.500000
AxisLowerLimit[1] = 1.000000
AxisLowerLimit[2] = 2.000000

AxisUpperLimit[0] = 11.000000
AxisUpperLimit[1] = 12.000000
AxisUpperLimit[2] = 13.000000

Now here's the actual debug output for the bit during load when it's transmitting the appropriate PlayerData datablock.

*** New Mission: dt/data/missions/dt_junction.mis
*** Phase 1: Download Datablocks & Targets
Mapping string: MissionStartPhase1Ack to index: 0

outgoing
0 : 5.500000 11.000000
outgoing
1 : 1.000000 12.000000
outgoing
2 : 2.000000 13.000000
incoming
0 : 0.456693 0.921260
incoming
1 : 1.000000 0.913386
incoming
2 : 0.992126 0.905512
outgoing
0 : 0.456693 0.921260
outgoing
1 : 1.000000 0.913386
outgoing
2 : 0.992126 0.905512
incoming
0 : 0.448819 0.913386
incoming
1 : 1.000000 0.905512
incoming
2 : 0.992126 0.897638

Could not locate texture: dt/data/shapes/carl/base.lmale
Could not locate texture: dt/data/shapes/carl/base.lmale
Validation required for shape: dt/data/shapes/carl/player.dts

I'm guessing it's a type problem, but for the life of me I can't work out what it is. Any help would be greatly appreciated.

Ian

#1
11/25/2003 (12:40 pm)
It might be the case that readFloat really wants to do a normalized value (ie, from 0-1).

I'd try upping the number of bits allocated to the float. 8 is really much too low if you want your value to pass unmolested. Try 16 or even 32 if you need "full precision".
#2
11/25/2003 (1:34 pm)
Thanks Ben.
Using 16 bits I get similar but slightly different results:

outgoing
0 : 5.500000 11.000000
outgoing
1 : 1.000000 12.000000
outgoing
2 : 2.000000 13.000000
incoming
0 : 0.499916 0.999847
incoming
1 : 1.000000 0.999832
incoming
2 : 0.999985 0.999817
outgoing
0 : 0.499916 0.999847
outgoing
1 : 1.000000 0.999832
outgoing
2 : 0.999985 0.999817
incoming
0 : 0.499916 0.999847
incoming
1 : 1.000000 0.999832
incoming
2 : 0.999985 0.999817

When I use 32, I get a fatal error in Bitstream.cc @ line 195 saying "out of range write". I looked at that AssertFatal but couldn't get any understanding of the problem.

Should I be using fixed point arithmetic?
Again, thanks for any help.
#3
11/25/2003 (3:19 pm)
From bitStream.h:
// read and write floats... floats are 0 to 1 inclusive, signed floats are -1 to 1 inclusive

   F32  readFloat(S32 bitCount);
   F32  readSignedFloat(S32 bitCount);

   void writeFloat(F32 f, S32 bitCount);
   void writeSignedFloat(F32 f, S32 bitCount);

So, you don't want to use those methods... try just doing:

stream->write(F32val);
stream->read(&F32val);
#4
11/25/2003 (3:25 pm)
Try this for the writes:

stream->write(axisLowerLimit[i]);

and this for the reads:

stream->read(&axisLowerLimit[i]);
#5
11/25/2003 (6:18 pm)
Thanks for the help guys.
I tried using stream->write and stream->read but I got the same "out of range write error". However, I don't see any particularly compelling reason not to simply divide my floats by 10, which would put them in the -1,1 brange, and then multiply them up again later.
It would be nice to know what the actual problem is though. I'm still betting I made a type error somewhere.

Thanks again,
Ian
#6
11/29/2003 (11:29 am)
You're probably putting too much data into the packet, if I was to guess.

(Thanks, Mark ;))
#7
03/12/2007 (10:26 pm)
Doesn't writing the raw float values to the stream a la...
stream->write(F32val);
stream->read(&F32val);
...break cross-platform compatibility?

Is it safe to stream->write() a float on a little-endian PC and stream->read() it on a big-endian Mac?