Float into 0.1

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,351
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
 
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.
 
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.
 
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
 
Back
Top Bottom