F64 or double in script
by Nathan Bowhay - ESAL · in Torque 3D Professional · 10/09/2010 (8:21 pm) · 10 replies
I was just wondering (haven't done any tests yet) if anyone noticed any issues with using double or F64 values in script. Seems most of torque uses F32 and we will need to use F64's for a ton of stuff since we are dealing with world coordinates.
Let me know if anyone knows of any issues I may run it to.
Let me know if anyone knows of any issues I may run it to.
#2
10/10/2010 (1:19 am)
Cool thanks for the info. Hopefully they make the change. If not I can just follow that thread. I was worried about something like that.
#3
Simply define a new get/set pair for F64 akin to what is being done for F32. Look in consoleTypes.h/cpp.
That *should* do it...
BTW, internally, the TorqueScript VM already operates on 64bit floats and integers.
10/16/2010 (2:39 am)
Simply define a new get/set pair for F64 akin to what is being done for F32. Look in consoleTypes.h/cpp.
That *should* do it...
BTW, internally, the TorqueScript VM already operates on 64bit floats and integers.
#4
and then getFloatValue is:
This seems a little odd, because what would be the point of returning a double if you are storing it as a float in the dictionary? I suppose if you ended up doing some math on it you could do the math as a double and have more precision.
10/21/2010 (6:16 pm)
I noticed in several places things like this:inline F64 ExprEvalState::getFloatVariable()
{
return currentVariable ? currentVariable->getFloatValue() : 0;
}and then getFloatValue is:
F32 getFloatValue()
{
if(type <= TypeInternalString)
return fval;
else
return dAtof(Con::getData(type, dataPtr, 0, enumTable));
}This seems a little odd, because what would be the point of returning a double if you are storing it as a float in the dictionary? I suppose if you ended up doing some math on it you could do the math as a double and have more precision.
#5
It seems like the intention behind this (which BTW has been there since TGE times) was to add some precision to the builtin math operations and avoid overflow through temporary operations. Like, if you add two numbers that and then divide.
However, IMO this is nonsense. Constants are 32bits (except for floats), variables are 32bits, everything else except the internal stacks is 32bits.
I'm pretty sure that all you would be when changing the stacks from 64bits to 32bits is a slight performance increase and no loss of precision to speak of.
10/21/2010 (6:30 pm)
Quote:what would be the point of returning a double if you are storing it as a float in the dictionary?
It seems like the intention behind this (which BTW has been there since TGE times) was to add some precision to the builtin math operations and avoid overflow through temporary operations. Like, if you add two numbers that and then divide.
However, IMO this is nonsense. Constants are 32bits (except for floats), variables are 32bits, everything else except the internal stacks is 32bits.
I'm pretty sure that all you would be when changing the stacks from 64bits to 32bits is a slight performance increase and no loss of precision to speak of.
#6
Ok so I added F64 to consoleTypes.h/.cpp:
I also added it to engineAPI.
I also added Point3D to mathTypes.h/.cpp:
Then I have a class that inherits from SimObject and has a EngineConsoleMethod:
There is a bit of network code that uses this:
It is then used like this:
Then in script the function that gets called looks like this:
I put a break point when handleNetMsg_callback is called and:
ecefPos = {x=-2306456.6662536608 y=-3646871.6080143028 z=4681200.4937747642 ...}
so that is what gets passed off.
Then there is a breakpoint in ConsoleGetType( TypePoint3D ) and:
pt = {x=-2306456.6662536608 y=-3646871.6080143028 z=4681200.4937747642 ...}
returnBuffer = "-2.30646e+006 -3.64687e+006 4.6812e+006"
Why is the return buffer like that?
Then there is a breakpoint in script and surprise surprise:
%ecefPos = -2.30646e+006 -3.64687e+006 4.6812e+006
Then I have a final breakpoint in DefineConsoleMethod( Earth, ECEFToLocal, Point3D, ( Point3D ecef )... and:
ecef = {x=-2306460.0000000000 y=-3646870.0000000000 z=4681200.0000000000 ...}
As you can see the get and set is incorrect or something and I am not sure why. The value cahnges from ecefPos = {x=-2306456.6662536608 y=-3646871.6080143028 z=4681200.4937747642 ...} to {x=-2306460.0000000000 y=-3646870.0000000000 z=4681200.0000000000 ...}. Which may not seem like a big deal but after being converted to local coordinates it is a difference of lot.
10/29/2010 (8:04 pm)
I am having some problems with the value not being correct after going to script. Note: I change some functions from their originals a little bit to make them simpler and not expose any propitiatory stuff. Also I left some stuff out, but you can assume it is correct, just read it and I will tell you the values after the code. If you need to know more just ask.Ok so I added F64 to consoleTypes.h/.cpp:
DefineConsoleType( TypeF64, F64 )
//-----------------------------------------------------------------------------
// TypeF64
//-----------------------------------------------------------------------------
ConsoleType( double, TypeF64, F64 )
ImplementConsoleTypeCasters(TypeF64, F64)
ConsoleGetType( TypeF64 )
{
char* returnBuffer = Con::getReturnBuffer(256);
dSprintf(returnBuffer, 256, "%lg", *((F64 *) dptr) );
return returnBuffer;
}
ConsoleSetType( TypeF64 )
{
if(argc == 1)
*((F64 *) dptr) = dAtod(argv[0]);
else
Con::printf("(TypeF64) Cannot set multiple args to a single F64.");
}I also added it to engineAPI.
template<>
struct EngineUnmarshallData< F64 >
{
F64 operator()( const char* str ) const
{
return dAtod( str );
}
};I also added Point3D to mathTypes.h/.cpp:
DECLARE_STRUCT( Point3D );
DefineConsoleType( TypePoint3D, Point3D )
IMPLEMENT_STRUCT( Point3D,
Point3D, MathTypes,
"" )
FIELD( x, x, 1, "X coordinate." )
FIELD( y, y, 1, "Y coordinate." )
FIELD( z, z, 1, "Z coordinate." )
END_IMPLEMENT_STRUCT;//-----------------------------------------------------------------------------
// TypePoint3D
//-----------------------------------------------------------------------------
ConsoleType( Point3D, TypePoint3D, Point3D )
ImplementConsoleTypeCasters(TypePoint3D, Point3D)
ConsoleGetType( TypePoint3D )
{
Point3D *pt = (Point3D *) dptr;
char* returnBuffer = Con::getReturnBuffer(256);
dSprintf(returnBuffer, 256, "%lg %lg %lg", pt->x, pt->y, pt->z);
return returnBuffer;
}
ConsoleSetType( TypePoint3D )
{
if(argc == 1)
dSscanf(argv[0], "%lg %lg %lg", &((Point3D *) dptr)->x, &((Point3D *) dptr)->y, &((Point3D *) dptr)->z);
else if(argc == 3)
*((Point3D *) dptr) = Point3D(dAtod(argv[0]), dAtod(argv[1]), dAtod(argv[2]));
else
Con::printf("Point3D must be set as { x, y, z } or \"x y z\"");
}Then I have a class that inherits from SimObject and has a EngineConsoleMethod:
DefineConsoleMethod( Earth, ECEFToLocal, Point3D, ( Point3D ecef ),,
"Convert the given ECEF position to local Cartesian coordinates.\n"
"@param ecef ECEF cartesian position to be converted to local cartisian position.\n"
"@return Local carteisan position converted from ecef.\n" )
{
Cartesian tempECEF(ecef);
Cartesian local;
object->ECEFToLocal(tempECEF, &local);
return Point3D(local);
}There is a bit of network code that uses this:
IMPLEMENT_GLOBAL_CALLBACK( handleNetMsg, void, (Point3D ecefPos), (ecefPos), "A callback to send a packet to script..\n" "@param ecefPos ECEF position x y z (meters)\n");
It is then used like this:
Point3D ecefPos(data.mEcefPosX, data.mEcefPosY, data.mEcefPosZ); //Let Torque Script do the rest handleNetMsg_callback(ecefPos);
Then in script the function that gets called looks like this:
function handleNetMsg(%ecefPos)
{
//Convert a global ECEF position to a local position
%pos = EarthObj.ECEFToLocal(%ecefPos);
}I put a break point when handleNetMsg_callback is called and:
ecefPos = {x=-2306456.6662536608 y=-3646871.6080143028 z=4681200.4937747642 ...}
so that is what gets passed off.
Then there is a breakpoint in ConsoleGetType( TypePoint3D ) and:
pt = {x=-2306456.6662536608 y=-3646871.6080143028 z=4681200.4937747642 ...}
returnBuffer = "-2.30646e+006 -3.64687e+006 4.6812e+006"
Why is the return buffer like that?
Then there is a breakpoint in script and surprise surprise:
%ecefPos = -2.30646e+006 -3.64687e+006 4.6812e+006
Then I have a final breakpoint in DefineConsoleMethod( Earth, ECEFToLocal, Point3D, ( Point3D ecef )... and:
ecef = {x=-2306460.0000000000 y=-3646870.0000000000 z=4681200.0000000000 ...}
As you can see the get and set is incorrect or something and I am not sure why. The value cahnges from ecefPos = {x=-2306456.6662536608 y=-3646871.6080143028 z=4681200.4937747642 ...} to {x=-2306460.0000000000 y=-3646870.0000000000 z=4681200.0000000000 ...}. Which may not seem like a big deal but after being converted to local coordinates it is a difference of lot.
#7
10/29/2010 (9:07 pm)
so apparently when I use %f it is a bit better, and %lf doesn't make a difference neither does %Lf or %LF. So I am not sure what to do cause it looks like there is something wrong with dSprintf.
#8
This is only for dSprintf for dSscanf %lg works, go figure.
10/29/2010 (9:45 pm)
seems like in the first reply (www.torquepowered.com/community/forums/viewthread/35604) they where saying to use %.9g and that seems to work, although I think a double is about 16 points of precision. Also it will make sure it has that many decimal places. I am still wondering why %lg doesn't work though.This is only for dSprintf for dSscanf %lg works, go figure.
#9
Yep, you need to ensure to have sufficient precision in the floating-point conversion or you'll see your numbers truncated like above.
The format flags not working for dSscanf looks like Microsoft not following conventions (dSscanf just uses sscanf). Even their own reference docs make this a little unclear. Alternatively, try %I64g.
10/29/2010 (10:44 pm)
Yep, you need to ensure to have sufficient precision in the floating-point conversion or you'll see your numbers truncated like above.
The format flags not working for dSscanf looks like Microsoft not following conventions (dSscanf just uses sscanf). Even their own reference docs make this a little unclear. Alternatively, try %I64g.
#10
11/01/2010 (6:22 pm)
Are you saying alternatively try %I64g with dSscanf or for dSprintf, because with dSscanf it still has the issue of displaying numbers with in scientific notation.
Torque 3D Owner Matt Huston
Atomic Banzai Games
I noted it in a bug report in T3D 1.1b2 - http://www.torquepowered.com/community/forums/viewthread/120265. I consider it a bug because I found someplace that Matt Fairfax said that shouldn't be the case a couple years back. I doubt it made it into T3D 1.1b3 since I reported it a week before release.