Notifications
Clear all

[Closed] Export 16 bit precision floating point

Can someone show me how to do this in max script using .net in max script is fine also This would such a great help for me and a lot of my friends. This is the type of float i am talking about
http://en.wikipedia.org/wiki/Half_precision_floating-point_format
I am not sure if we can call this or something close to it
http://msdn.microsoft.com/en-us/library/ff471399(VS.85).aspx
this also describes in xna
http://social.msdn.microsoft.com/Forums/en-US/xnaframework/thread/9af86142-60ee-4087-b685-b7bfbeca74eb

8 Replies

If you install Microsoft’s free XNA Studio it adds support for ‘half’ formats, stuff like:

struct HalfSingle
Member of Microsoft.Xna.Framework.Graphics.PackedVector

Summary:
Packed vector type containing a single 16 bit floating point value.

struct HalfVector4
Member of Microsoft.Xna.Framework.Graphics.PackedVector

Summary:
Packed vector type containing four 16-bit floating-point values.

(Remove the extra spaces after PackedVector.Half that get added to this code by the forum tools )

assm = dotnet.loadassembly "Microsoft.Xna.Framework.dll"
half = dotnetobject "Microsoft.Xna.Framework.Graphics.PackedVector.HalfSingle" 1.23
bit.intAsHex half.packedvalue

halfV4 = dotnetobject "Microsoft.Xna.Framework.Graphics.PackedVector.HalfVector4" 1.0 2.0 3.0 4.0
halfV4.packedvalue
halfV4.tostring()

This generates the following on my Max2009 system:

dotNetObject:Microsoft.Xna.Framework.Graphics.PackedVector.HalfSingle
“3cec”
dotNetObject:Microsoft.Xna.Framework.Graphics.PackedVector.HalfVector4
4899988963420290048L
“{X:1 Y:2 Z:3 W:4}”

You should be able to write out the packed values in your exporter.

.biddle

bit.intAsHex (bit.floatAsInt 1.0) gives “3f800000”, which is a f32 version of the number 1.0
Now you should be able to extract the exponent and the number and re-encode them in f16.

Thanks for your replies

biddle
when i run
assm = dotnet.loadassembly “Microsoft.Xna.Framework.dll”
i get this error

Runtime error: dotNet runtime exception: Could not load file or assembly 'Microsoft.Xna.Framework, Version=3.1.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d' or one of its dependencies. The system cannot find the file specified.

Oormi
also Do you have an example of encoding it to float 16 that would be a big help if you did.

Try loading the assembly with a complete path:

dotnet.loadassembly @"C:\Program Files\Microsoft XNA\XNA Game Studio\v3.1\References\Windows\x86\Microsoft.Xna.Framework.dll"

ok this first line works

dotnet.loadassembly @"C:\Program Files (x86)\Common Files\microsoft shared\XNA\DeployableRuntimes\Zune\3.1.10527.100\Microsoft.Xna.Framework.dll"
half = dotnetobject "Microsoft.Xna.Framework.Graphics.PackedVector.Half Single" 1.23

but now i get
– Error occurred in anonymous codeblock; filename: C:\Program Files\Autodesk\3ds Max 2010\Scripts; position: 226; line: 2
– Runtime error: Cannot resolve type: Microsoft.Xna.Framework.Graphics.PackedVector.Half

Thanks again for all your help

It’s a “HalfSingle” –all one word. You need to remove the space

The CGTalk forum software has a nasty habit of inserting spaces into what it thinks are long words of code.

halfstr = "Microsoft.Xna.Framework.Graphics" + ".PackedVector.HalfSingle"
half = dotnetobject halfstr 1.23

I found this online ma bee this is possible to convert to native max script i will give it a try if anyone has any suggestions they are welcome

const
HalfMin: Single = 5.96046448e-08; // Smallest positive half
HalfMinNorm: Single = 6.10351562e-05; // Smallest positive normalized half
HalfMax: Single = 65504.0; // Largest positive half
HalfEpsilon: Single = 0.00097656; // Smallest positive e for which half (1.0 + e) != half (1.0)
HalfNaN: THalfFloat = 65535;
HalfPosInf: THalfFloat = 31744;
HalfNegInf: THalfFloat = 64512;

{

Half/Float conversions inspired by half class from OpenEXR library.

Float (Pascal Single type) is an IEEE 754 single-precision

floating point number.

Bit layout of Single:

31 (msb)
|
| 30     23
| |      |
| |      | 22                    0 (lsb)
| |      | |                     |
X XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX
s e        m

Bit layout of half:

15 (msb)
|
| 14  10
| |   |
| |   | 9        0 (lsb)
| |   | |        |
X XXXXX XXXXXXXXXX
s e     m

S is the sign-bit, e is the exponent and m is the significand (mantissa).
}

function HalfToFloat(Half: THalfFloat): Single;
var
Dst, Sign, Mantissa: LongWord;
Exp: LongInt;
begin
// extract sign, exponent, and mantissa from half number
Sign := Half shr 15;
Exp := (Half and $7C00) shr 10;
Mantissa := Half and 1023;

if (Exp > 0) and (Exp < 31) then
begin
// common normalized number
Exp := Exp + (127 – 15);
Mantissa := Mantissa shl 13;
Dst := (Sign shl 31) or (LongWord(Exp) shl 23) or Mantissa;
// Result := Power(-1, Sign) * Power(2, Exp – 15) * (1 + Mantissa / 1024);
end
else if (Exp = 0) and (Mantissa = 0) then
begin
// zero – preserve sign
Dst := Sign shl 31;
end
else if (Exp = 0) and (Mantissa <> 0) then
begin
// denormalized number – renormalize it
while (Mantissa and $00000400) = 0 do
begin
Mantissa := Mantissa shl 1;
Dec(Exp);
end;
Inc(Exp);
Mantissa := Mantissa and not $00000400;
// now assemble normalized number
Exp := Exp + (127 – 15);
Mantissa := Mantissa shl 13;
Dst := (Sign shl 31) or (LongWord(Exp) shl 23) or Mantissa;
// Result := Power(-1, Sign) * Power(2, -14) * (Mantissa / 1024);
end
else if (Exp = 31) and (Mantissa = 0) then
begin
// +/- infinity
Dst := (Sign shl 31) or $7F800000;
end
else //if (Exp = 31) and (Mantisa <> 0) then
begin
// not a number – preserve sign and mantissa
Dst := (Sign shl 31) or $7F800000 or (Mantissa shl 13);
end;

// reinterpret LongWord as Single
Result := PSingle(@Dst)^;
end;

function FloatToHalf(Float: Single): THalfFloat;
var
Src: LongWord;
Sign, Exp, Mantissa: LongInt;
begin
Src := PLongWord(@Float)^;
// extract sign, exponent, and mantissa from Single number
Sign := Src shr 31;
Exp := LongInt((Src and $7F800000) shr 23) – 127 + 15;
Mantissa := Src and $007FFFFF;

if (Exp > 0) and (Exp < 30) then
begin
// simple case – round the significand and combine it with the sign and exponent
Result := (Sign shl 15) or (Exp shl 10) or ((Mantissa + $00001000) shr 13);
end
else if Src = 0 then
begin
// input float is zero – return zero
Result := 0;
end
else
begin
// difficult case – lengthy conversion
if Exp <= 0 then
begin
if Exp < -10 then
begin
// input float’s value is less than HalfMin, return zero
Result := 0;
end
else
begin
// Float is a normalized Single whose magnitude is less than HalfNormMin.
// We convert it to denormalized half.
Mantissa := (Mantissa or $00800000) shr (1 – Exp);
// round to nearest
if (Mantissa and $00001000) > 0 then
Mantissa := Mantissa + $00002000;
// assemble Sign and Mantissa (Exp is zero to get denotmalized number)
Result := (Sign shl 15) or (Mantissa shr 13);
end;
end
else if Exp = 255 – 127 + 15 then
begin
if Mantissa = 0 then
begin
// input float is infinity, create infinity half with original sign
Result := (Sign shl 15) or $7C00;
end
else
begin
// input float is NaN, create half NaN with original sign and mantissa
Result := (Sign shl 15) or $7C00 or (Mantissa shr 13);
end;
end
else
begin
// Exp is > 0 so input float is normalized Single

  // round to nearest
  if (Mantissa and $00001000) &gt; 0 then
  begin
    Mantissa := Mantissa + $00002000;
    if (Mantissa and $00800000) &gt; 0 then
    begin
      Mantissa := 0;
      Exp := Exp + 1;
    end;
  end;
  if Exp &gt; 30 then
  begin
    // exponent overflow - return infinity half
    Result := (Sign shl 15) or $7C00;
  end
  else
    // assemble normalized half
    Result := (Sign shl 15) or (Exp shl 10) or (Mantissa shr 13);
end;

end;
end;

Ah this is a much more compact version can someone help implementing this?

http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf