Float into 0.1

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,266
I'm trying to understand how this particular code from GameDev works. It's supposed to encode a floating point number into multiple numbers of range 0.0 - 1.0 (taking consideration to any overlapping), and then back again.


Below is a first try to write it in Cerberus, but it won't output what you'd expect? What am I doing wrong here?

Code:
Import mojo2

Function Main()
    New MyApp
End

Class MyApp Extends App

    Field canvas:Canvas
   
    Method OnCreate()
        canvas = New Canvas ; SetUpdateRate 0
       
        Local value:Float = 20.0
       
        ' Float2Int:void(value:Float)  
        Local tofixed:Float = 255.0/256.0      
        Local r:Float = frac(value * tofixed*1.0)
        Local g:Float = frac(value * tofixed*255.0)  
   
        ' Int2Float:value()
        Local fromfixed:Float = 256.0/255.0
        Local out:Float
        out = r * fromfixed/(1.0) + g * fromfixed/(255.0)
       
        Print out ' Should Print 20.0 (Not 0.925..)

    End
   
    Method OnUpdate()
    End
   
    Method OnRender()
         canvas.Clear
        canvas.Flush
    End
   
    Function frac:Float(value:Float)
        Return value - Floor(value)
    End
   
End
 

vitaliano.neto

New member
Joined
Apr 28, 2022
Messages
3
Hi Wingnut,

From what I've read in the thread you can only use this technique to store values between 0 and 1.
To use it with 20 like you do, you need to normalize it, and when converting back you will need to denormalize it (or should I say unnormalize it 🤔) .

Here is what corysama wrote about this:
If you want to store a value over 1, you need to know what your range is. Before converting floatToFixed,you will need to divide by the range to map [0,range] down to [0,1]. Then when converting back with fixedToFloat you multiply the [0,1] value by the maximum range.
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,266
Hi Wingnut,

From what I've read in the thread you can only use this technique to store values between 0 and 1.
To use it with 20 like you do, you need to normalize it, and when converting back you will need to denormalize it (or should I say unnormalize it 🤔) .

Here is what corysama wrote about this:
Oh so it's just for storing float 0.0 - 1.0 right now, ya I can see that is working I can put away 0.0-1.0 and it recreates it with some minor errror. But was that what they meant? I thought it was about storing any float into four 0.0-1.0 bytes.

I need to read this again as it seems to work just fine for 0.0-1.0. Maybe you use it to save with greater precision.
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,266
I tried another version but I think the first one has stronger precision.

Code:
Import mojo2

Function Main()
    New MyApp
End

Class MyApp Extends App

    Field canvas:Canvas
  
    Method OnCreate()
        canvas = New Canvas ; SetUpdateRate 0
      
        Local value:Float = 0.5
      
        ' EncodeFloatRGBA
        Local r:Float,g:Float,b:Float,a:Float
        r = frac(value * 1.0)
       g = frac(value * 255.0)
        b = frac(value * 65025.0)
        a = frac(value * 160581375.0)
        r = r - g * 1.0/255.0
       g = g - b * 1.0/255.0
        b = b - a * 1.0/255.0
 
        ' DecodeFloatRGBA
        Local out:Float
        out = r * 1.0 + g * (1.0/255.0) + b * (1.0/65025.0) + a * (1.0/160581375.0) 
        
        Print out ' 0.4999999...

    End
  
    Method OnUpdate()
    End
  
    Method OnRender()
         canvas.Clear
        canvas.Flush
    End
  
    Function frac:Float(value:Float)
        Return value - Floor(value) ' fract would be value-(long)value in c++ (same as modf)
    End
  
End
 
Top Bottom