Masking or occluding image strips in real time?

Blitz3D Forums/Blitz3D Programming/Masking or occluding image strips in real time?

Avrigus(Posted 2008) [#1]
Hey Everyone,

I have a problem that i've been trying to solve on my own for weeks. I want to make an odometer to act as a hi score counter on my HUD so i've created an image strip with the numbers 0 - 9.

Now I have no problem writing code that steps through the numbers vertically on the image strip; the problem I face is masking or occluding the strip so it only shows one digit at a time (exactly like the odometer in a car).

I've toyed with the idea of making a new camera and making its viewport the size of the odometer area but the problem there is that I want the background to be transparent and I want to be able to have elements from the primary camera viewport to pass in front of the odometer if necessary.

I have been using a combination of Sprite Candy and FastImage. Any help would be great :-)


KillerX(Posted 2008) [#2]
Use the function LoadAnimImage() to animate it, and MaskImage to mask it. You will need to use drawimage after RenderWorld() so that it is drawn.


Uncle(Posted 2008) [#3]
I would use a sprite or quad and then texture it with your number texture. Scale the texture so only one number fits on the sprite. Then use the positiontexture command to scroll the texture on the sprite. Below is some rough code to give you the idea. You will have to use your own image but basically it should have the numbers from 0 to 9 going vertically down it equally spaced.

Graphics3D 800,600,0,2

cam=CreateCamera()

numbersprite=CreateSprite()
PositionEntity numbersprite,0,0,10

numbertexture=LoadTexture("numbers.png",1+2)
ScaleTexture numbertexture,10,10
EntityTexture numbersprite,numbertexture

ycount#=1
While Not KeyDown(1)
	PositionTexture numbertexture,1,ycount
	ycount=ycount-0.005
	If ycount=0 Then ycount=1
	RenderWorld
	Flip
Wend


You can download the source with the media for the example at http://www.urbaninteractive.net/Numbers.zip

Hope this helps.


Ross C(Posted 2008) [#4]
For extra crispness, ensure your texture is in powers of 2.

16x256
or
128x32

etc etc

Blitz will scale UP any non power of 2 dimensions.

And don't use a ratio of more than 8:1 between the dimensions.


Avrigus(Posted 2008) [#5]
Thanks for your solution Uncle, animating the texture of a quad is a very elegant solution.

I do have another situation where i'd like to use a similar technique although it's a little more complicated. I want to create a slot machine with 3 reels and each reel would have around 30 random symbols.

Rather than making a massively long image strip, is there a way I can dynamically add (or remove) individual symbol images to a dynamically scrolling texture?


Dreamora(Posted 2008) [#6]
don't make it a scroling texture. build the "slot wheel" mesh dynamically selecing different frames of that texture strip.
as textures are nothing else than something you can assign to geometry (they don't exist without it), thats the way to dynamically use them.


Avrigus(Posted 2008) [#7]
@Dreamora: Having a fixed quad would be preferable since if I built a "slot wheel" I would have to occlude the area of the wheel that goes behind the reel surround (I have the reel surround as a background element and the reel acts like an overlay).

I will post an exe later today of what I have so far so you can see exactly what i'm doing :-)


Ross C(Posted 2008) [#8]
30 symbols isn't too much for a texture IMO.

For example, 42x42 for each symbol. 6 x 6 symbols

6 x 42 pixels = 252.

So, basically a 256 x 256 texture would do your needs, as it would hold 36 (6x6). You'd just need a little more code to select the correct frame, since it will be arranged like a grid.


Avrigus(Posted 2008) [#9]
Here's an example of what I have working at the moment. You can see that I need to clip the symbols above and below the reel surrounds:



If you would like to see it in action you can download the executable here:
http://www.avrigus.com/Simon_Reel_Test.zip

Any help or solutions would be great! :-)


Uncle(Posted 2008) [#10]
Indeed this it completely different problem, because the sprites are not scrolled in sequence. Solving this would be easy if you didnt need to preserve alpha values in your images, because you could simply make the texture on the fly by using copyrects.

I think though the best solution is to use spritecandy as you are doing and instead you will need several sprites. You will then need to change the sprite sizes and crop areas to give the appearance of scrolling. I've made a brief demo to show what I mean. http://www.urbaninteractive.net/Reel.zip

You never know though someone might come up with an easier way.


Dreamora(Posted 2008) [#11]
well if you make your slot machine a 2 part image -> the part behind the wheels which is drawn before the 3D part and the slot machine drawn after, you can actually use the image to "clip" what you see, without any problem.

the alternative is dx7test.dll / fastextends and use render to texture with a real wheel into a texture that you just use there on a single quad.


Uncle(Posted 2008) [#12]
well if you make your slot machine a 2 part image -> the part behind the wheels which is drawn before the 3D part and the slot machine drawn after, you can actually use the image to "clip" what you see, without any problem.


Perhaps I missunderstood, but I think this would be true if the background was a solid static image. However the backgroud is a dynamic 3D room which spins. Simply changing the draw order wouldn't solve the problem. Did you run his demo to see what the problem was?


Avrigus(Posted 2008) [#13]
Wow thank you for that awesome solution! I didn't even know that was possible using Sprite Candy. I don't necessarily need to preserve the alpha of the symbols (I was going to combine the symbol background with the symbol graphic in code).

I have no experience with the copyrect command, how would I go about integrating it into my Sprite Candy driven scene?


Uncle(Posted 2008) [#14]
For the copyrect method you don't need to worry about SpriteCandy as you can do it all in native blitz. Here's the code (use the reel.png from the last example)

Graphics3D 800,600,0,2
Global cam=CreateCamera()
Const spriteSize=64
Global reelSprite=CreateSprite()
Global scrollPos#=1
PositionEntity reelSprite,0,0,3
cube=CreateCube()
light=CreateLight(2)
LightRange light,3
PositionEntity cube,0,0,5

Global masterTexture%=LoadTexture("reel.png")
Global reelTexture%=CreateTexture(128,1024,16) ;// Taking into account what Ross C said about max of 8:1 ratio

;// Make a reel using random tiles 
;// Just copy random tiles from the master texture, directly onto our new reelTexture
For x=0 To 1023 Step 64
	CopyRect(Rand(0,7)*spriteSize,Rand(0,7)*spriteSize,spriteSize,spriteSize,0,x,TextureBuffer(masterTexture),TextureBuffer(reelTexture))
Next
;// Now scale the texure so we only see a few tiles and apply it to the reelSprite
ScaleSprite reelSprite,(0.25),1
ScaleTexture reelTexture,(0.125)*16,(1)*5
EntityTexture reelSprite,reelTexture


;// Now the main loop to scroll the texure on the reelSprite
While Not KeyDown(1)
	If scrollPos<1 Then 
		scrollPos=scrollPos+0.001
	Else
		scrollPos=0
	EndIf
	PositionTexture reelTexture,0,scrollPos
	EntityColor cube,Rand(255),Rand(255),Rand(255)
	TurnEntity cube,1,1,0
	RenderWorld
	Flip 
Wend


it will look a little ugly because the png has a transparent background, but if this was solid then it would look fine. Unfortunately copyrect doesnt copy alpha info, and thats why I used spritecandy previously as I thought you needed to do this.


Ross C(Posted 2008) [#15]
For clipping, why not set the camera viewport to the area you want the 3d stuff done?