Recent

Author Topic: Mapping Images Like Odometer  (Read 1239 times)

SandyG

  • Full Member
  • ***
  • Posts: 121
Mapping Images Like Odometer
« on: September 08, 2025, 02:13:25 am »
Was thinking of the next fun component to work on. I always like the basic Odometer from older cars as something fun. Seen a few in Javascript, but hard to translate to Pascal/BGRA so looking for some hints how to do something like this (Ignore the gear sprockets for now). The odometer is basically a slot machine wheel. The image that is spun has to be 'Bent' to the wheel diameter, and likely has some shading on the top or bottom (This is the easy part as can likely fake the eye out with simple shading).

1. Wheels could have arbitrary image, like a number, letter, or an image (Think of a slot machine)
2. Stack arbitrary number of 'wheels'
3. Partial images as the wheel rolls around and support arbitrary 'roll angle' so can possibly animate the wheel moving
4. Related Background, Spacing, etc.

I was playing with some of the BGRA's FillPolyPerspectiveMapping() function as a possible way to do with some lower fidelity in the wrapping ability to, again just trick the eye in seeing some depth to make it look like it's wrapping.

The idea would be to generate a Bitmap of all the characters and do a 'lens' over the area of interest to map / translate the area of the image to be bent like on a wheel.

Not sure if this is a simple geometric transformation (given a cylinder diameter create a function to scale the width of a scan line???).

Open for help and staring points, or if you know of a component that I can work on like this that's even better.

Thanks

Sandy

circular

  • Hero Member
  • *****
  • Posts: 4457
    • Personal webpage
Re: Mapping Images Like Odometer
« Reply #1 on: November 03, 2025, 11:30:16 am »
Hi Sandy,

Making an odometer seems like a fun idea  :)

I suppose there are various level of detail in the transformation :
  • not transform, just translate and the symbols are clipped. This is simplistic but actually often done.
  • do a lense effect so that the symbols are shrunk vertically at the top and bottom instead of being clipped.
  • do a full 3D effect so that the symbols are shrunk vertically but also slightly reduced horizontally.

Doing the vertical shrinking is not too difficult to do. It is indeed a cylinder transformation and you only need a formula to map the Y coordinate. For the full 3D effect, you need to map the X coordinate as well or use actual 3D drawing function like FillPolyPerspectiveMapping.

You can start by making a custom scanner to do the cylinder transform. It would be a bit similar to TBGRAVerticalCylinderDeformationScanner that you can find in BGRATransform unit, except that it changes the other coordinate. Also you probably want to have a source image that is bigger vertically by a factor of Pi/2, so that in the middle, the image is not stretched.

The scanner would be something like that (not tested and not optimized):

Code: Pascal  [Select][+][-]
  1. const
  2.   OdometerDeformationSourceRatio = 1.570796326794897; {PI/2}
  3. type
  4.   { Scanners that distorts as a horizontal cylinder shape with a ratio }
  5.   TBGRAOdometerDeformationScanner = Class(TBGRACustomScanner)
  6.   protected
  7.     FScanner: IBGRAScanner;
  8.     FScanAtFunc: TScanAtFunction;
  9.     FCenterY: single;
  10.     FRadiusY: single;
  11.     FSourceRatioY: single;
  12.   public
  13.     constructor Create(AScanner: IBGRAScanner; ATargetSizeY: single;
  14.       ASourceRatioY: single = OdometerDeformationSourceRatio);
  15.     function ScanAt(X, Y: Single): TBGRAPixel; override;
  16.   end;
  17.  
  18. constructor TBGRAOdometerDeformationScanner.Create(
  19.   AScanner: IBGRAScanner; ATargetSizeY: single; ASourceRatioY: single);
  20. begin
  21.   FScanner := AScanner;
  22.   FScanAtFunc := @FScanner.ScanAt;
  23.   FCenterY := ATargetSizeY/2 - 0.5;
  24.   FRadiusY := ATargetSizeY/2;
  25.   FSourceRatioY := ASourceRatioY;
  26. end;
  27.  
  28. function TBGRAOdometerDeformationScanner.ScanAt(X, Y: Single): TBGRAPixel;
  29. var
  30.   yn: Single;
  31. begin
  32.   // computes normalized position [-1..1] on target
  33.   yn := (y - FCenterY) / FRadiusY;
  34.   if (abs(yn) <= 1) then
  35.   begin
  36.     // apply curvature
  37.     yn := (2 / Pi) * arcsin(yn);
  38.     // retrieve pixel in source
  39.     result := FScanAtFunc(x, (yn * FRadiusY + FCenterY)*FSourceRatioY);
  40.   end
  41.   else
  42.     result := BGRAPixelTransparent; // outside of range
  43. end;
Conscience is the debugger of the mind

SandyG

  • Full Member
  • ***
  • Posts: 121
Re: Mapping Images Like Odometer
« Reply #2 on: November 14, 2025, 06:56:55 am »
OK, going to find some time to work on this. Had to take a break for a bit, but looking for more late night fun.

Have to start looking at the code and build a simple sample.

The odometer would be just one application, I keep thinking of a slot machine as well :)

Thanks for the help to get a jump start on this.

Sandy


SandyG

  • Full Member
  • ***
  • Posts: 121
Re: Mapping Images Like Odometer
« Reply #3 on: November 14, 2025, 11:53:01 pm »
Got it working to roll an image around.

Didn't realize how the scanners worked, but really this is just the Horizontal version of the mapping to a cylinder.

Have to play around with some parameters so you could easily adjust 'wheel' diameter, width, and faster mapping.

My strategy will be to make an array of what ever the images are for the wheel, ie, digits, or images. Then figure out how to draw them quickly as it would scroll showing top and bottoms of rolling images to simulate the wheel.

Not quite sure yet how to do it all, but the simple test program rolling a text in and out of the view looks really good.

Some more time to ponder :)

Sandy

« Last Edit: November 14, 2025, 11:55:44 pm by SandyG »

circular

  • Hero Member
  • *****
  • Posts: 4457
    • Personal webpage
Re: Mapping Images Like Odometer
« Reply #4 on: November 16, 2025, 09:36:27 pm »
Glad it worked  :)

I guess you can enrich the scanner by adding multiple sources, etc.

Cheers
Conscience is the debugger of the mind

SandyG

  • Full Member
  • ***
  • Posts: 121
Re: Mapping Images Like Odometer
« Reply #5 on: December 01, 2025, 06:46:14 pm »
Just some continued playing with drawing. This does not draw with the image mapped to a cylinder, just flat. .Using the Phong shader that does have a horizontal cylinder mapper. So was really easy for a change. Need to add the shading code to the other to see how it will look. Even without the mapping of the image to the cylinder, the shading depth que makes it look better.


SandyG

  • Full Member
  • ***
  • Posts: 121
Re: Mapping Images Like Odometer
« Reply #6 on: December 03, 2025, 12:22:35 am »
Ugg, just thought of this, need to apply this as a mask to the image not just draw on the shaded background. A bit more work, but will be better since the shadow/light will affect the image/text in a better way.

SandyG

  • Full Member
  • ***
  • Posts: 121
Re: Mapping Images Like Odometer
« Reply #7 on: December 03, 2025, 08:15:01 am »
Made some updated to the drawing, looking nicer!

circular

  • Hero Member
  • *****
  • Posts: 4457
    • Personal webpage
Re: Mapping Images Like Odometer
« Reply #8 on: December 08, 2025, 06:41:24 pm »
It's also nice. Can't wait to see the animation of it.  :)
Conscience is the debugger of the mind

SandyG

  • Full Member
  • ***
  • Posts: 121
Re: Mapping Images Like Odometer
« Reply #9 on: December 09, 2025, 08:06:30 pm »
Here are links to the ongoing test.

This one just uses the 200x600 pix image and rolls that around. Have to make some mods to do continuous rolling. Likley add a couple of images to it, top and bottom and then just adjust the drawing start and end points.

4.1meg Windows EXE, and the needed JPG image.

https://drive.google.com/file/d/1931lmby8AH3z-WBVzrqEbc1SCveZx1Go/view?usp=sharing
https://drive.google.com/file/d/1ciRNgUFnQSk5kqG9W7wI1zSPfO4goLZI/view?usp=sharing

Simple 50 ms time moving the wheel, not sure if the best way to do it, but seems good enough for testing.
You can change the scroll speed by the slider, basically just changes how many pixels the drawing is offset by.
Manual buttons for moving as well.
« Last Edit: December 09, 2025, 08:10:49 pm by SandyG »

circular

  • Hero Member
  • *****
  • Posts: 4457
    • Personal webpage
Re: Mapping Images Like Odometer
« Reply #10 on: Today at 08:58:33 am »
Hi Sandy,

Thanks for sharing.

Even though I would rather trust you in this case, it would be better to avoid sending binaries, because they could contain malwares or viruses.

I checked with virustotal anyway:
https://www.virustotal.com/gui/file/f1ebdcbe9314b1c452f737a18ca53e6e9face817914571c461f58de1ac4fd31b?nocache=1

I tried it and I love it <3

Using a 50 ms timer is ok, I would suggest 30 ms instead, so that it is fluid and at the same time it would probably not block the event loop. If it is too small, it could prevent the window from closing.

I guess next improvement is to scroll when clicking and dragging. It could give it some impulse to rotate.
Conscience is the debugger of the mind

SandyG

  • Full Member
  • ***
  • Posts: 121
Re: Mapping Images Like Odometer
« Reply #11 on: Today at 05:22:27 pm »
Yeah, I don't normally like to do a binary exe but was really lazy :)

Thank you for the encouraging words as well!!

Due to the 'Power' of the BGRA libraries, and some set up of the shader, OdometerScanner it makes for the drawing code very simple. I tried all the different Blends and the boHardLight worked really well, and didn't really mind black and white differences. Long ways to go but looking better each time I hack it up. Now on to more of the controls and logic.

Code: Pascal  [Select][+][-]
  1.   // Paint code
  2.  
  3.   tex.PutImage(0, FYOffset, wheelImage, dmSet); // move start position
  4.   image.Fill(FOdoScanner);                      // Use the custom Odometer Scanner
  5.   image.BlendImage(0, 0, Map, boHardLight);     // Seems to look good on black or white backgrounds
  6.   image.Draw(Canvas, 0, 0, True);

I have to do a lot of little stuff to get it going still. On the list -

1. Roll around logic
2. Text Only so no images are needed
3. Multi-wheel, with next wheel trigger
4. Borders, spacers and frame
5. Drag motions (useful for a knob like wheel)
6. Make it a component, expose all the options, etc.

« Last Edit: Today at 05:28:32 pm by SandyG »

 

TinyPortal © 2005-2018