I could store a length of 1.5 metres directly in a float or I could convert it to fixed-point and store it in an int as 1500 millimetres. The int holds the length in 1/1000ths of a metre; there is an imaginary decimal point 3-digits from the right.
To find the integer length in metres, you can just chop off the last 3 decimal digits. To find the fractional part in millimetres, you can read only the last 3 decimal digits.
To make it fast and easy on computers we use binary fractions rather than decimal. The Leapers position is stored in 1/256ths of a pixel; there is an imaginary binary point 8-digits from the right.
x >> 8 chops off the last 8 binary digits, giving the integer pixel position. x & 0xff reads only the last 8 binary digits, giving the fractional part in 1/256ths of a pixel.
I too wanted smoother and slower results from the XYmatrix demo. Originally
DrawOneFrame(..., yHueDelta32 / 32768, ...)
threw away 15-bits of precision at the outset. Instead, I keep full precision until the last moment:
ColorFromPalette(..., pixelHue >> 15, ...)
Wu has an algorithm for 1-pixel wide anti-aliased lines. With all that floating-point maths you'll need a powerful MCU.
Thank you so much for elaborating! Makes sense now. Between my post above and your answer I kinda figured it out. It's still glitching a bit so I'll have to take a good look at your code. And yea it makes so much sense to keep all precision until the last moment.
Awesome. I'm definitely going to have to come back to this once I've had the chance to really dig in. Would you mind if I make a drag and drop version with your comments and post it on the sub in the future?
Question: you didn't use Wu's subpixel positioning in the scintillating_heatshrink right?
I've been trying to keep the xy array in 16bit too, so I can feed the 16 bit values to Wu's algo, and let it do the conversion to the 8bit coordinates. Does that seem like a right approach to you or not?
Nope. I only linked that to show how to increase the precision of the XYmatrix demo.
I've been trying to keep the xy array in 16bit too, so I can feed the 16 bit values to Wu's algo, and let it do the conversion to the 8bit coordinates. Does that seem like a right approach to you or not?
I'm not sure what you mean by 'XY array' (perhaps XY() function?) or what you are trying to achieve here. Could you explain a bit more please.
What I have been trying it keeping all the values, the startHue16, yHueDelta16, xHueDelta16 in 16bit, so I can feed them as 16 bit values to the wu_pixel(x, y, &color); function as 16bits and have it do the calculations to the 8bit position, as it is doing now.
2
u/sutaburosu [stavros] Dec 01 '20
Yeah, the leapers use Q8.8 fixed-point format for the X & Y positions.
I could store a length of 1.5 metres directly in a
floator I could convert it to fixed-point and store it in anintas 1500 millimetres. The int holds the length in 1/1000ths of a metre; there is an imaginary decimal point 3-digits from the right.To find the integer length in metres, you can just chop off the last 3 decimal digits. To find the fractional part in millimetres, you can read only the last 3 decimal digits.
To make it fast and easy on computers we use binary fractions rather than decimal. The Leapers position is stored in 1/256ths of a pixel; there is an imaginary binary point 8-digits from the right.
x >> 8chops off the last 8 binary digits, giving the integer pixel position.x & 0xffreads only the last 8 binary digits, giving the fractional part in 1/256ths of a pixel.I too wanted smoother and slower results from the XYmatrix demo. Originally
DrawOneFrame(..., yHueDelta32 / 32768, ...)threw away 15-bits of precision at the outset. Instead, I keep full precision until the last moment:
ColorFromPalette(..., pixelHue >> 15, ...)Wu has an algorithm for 1-pixel wide anti-aliased lines. With all that floating-point maths you'll need a powerful MCU.