Dark Bit Factory & Gravity
PROGRAMMING => Freebasic => Topic started by: Clyde on January 24, 2010
-
Hi,
This is heavily inspired by Shockwave as I love the effect so much.
What the problem is, is that the drawing of the image \ texture isnt being rendered properly. I'd would love to see what's not quite right.
' textured twister.
' based on code kindly produced and written by shockwave^codigos
' uses tinyptc extension++.bi by rbz^codigos
'
option static
option explicit
#include once "tinyptc_ext++.bi"
const as single PI = 3.141593
const as single DEGREES = ( PI / 180.00 )
const as integer MONITOR_SPEED = 60
type graphics_buffer
as integer wwidth, height
as integer wwidth2, height2
as uinteger ptr pixels
end type
declare sub clear_graphics_buffer ( byval buffer as graphics_buffer ptr, byval argb as uinteger=0 )
declare sub run_demo ()
declare sub init_demo ()
declare sub update_twisty ( byval dest as graphics_buffer ptr,_
byval texture as graphics_buffer ptr,_
byval bar_wwidth as integer=150)
declare function create_graphics_buffer( byval wwidth as integer, byval height as integer ) as graphics_buffer ptr
declare function graphics ( byval title as string,_
byval wwidth as integer,_
byval height as integer,_
byval options as integer=0 ) as graphics_buffer ptr
dim shared as single sinus_add1, sinus_add2
dim shared as single old_time, new_time, delta
dim shared as graphics_buffer ptr screen_buffer, image_buffer
init_demo ()
run_demo ()
ptc_close ()
sub clear_graphics_buffer(byval buffer as graphics_buffer ptr, byval argb as uinteger=0 )
dim as uinteger ptr pixel =buffer->pixels
dim as integer length=buffer->wwidth*buffer->height
asm
mov eax,dword ptr[argb]
mov ecx,dword ptr[length]
mov edi,dword ptr[pixel]
rep stosd
end asm
end sub
sub init_demo()
screen_buffer =graphics("twiST aND shOUt", 640, 480 )
image_buffer =create_graphics_buffer( 128, screen_buffer->height )
for y as integer=1 to image_buffer->height-2
for x as integer=1 to image_buffer->wwidth-2
image_buffer->pixels[ x+y*image_buffer->wwidth ]=&hf064f0
next
next
end sub
sub run_demo()
while inkey<>chr(27)
old_time=timer()
clear_graphics_buffer( screen_buffer )
update_twisty ( screen_buffer, image_buffer )
ptc_update ( @screen_buffer->pixels[0] )
new_time = (timer()-old_time)+.01
delta = new_time*MONITOR_SPEED
wend
end sub
sub update_twisty( byval dest as graphics_buffer ptr, byval texture as graphics_buffer ptr, byval bar_wwidth as integer=150 )
dim as integer x, scanline_y,x1,x2,x3,x4, pos_x, v
dim as integer sinus, sinus_wwidth1, sinus_wwidth2, wwidth2
dim as uinteger colour
dim as uinteger ptr dest_ptr
dim as single inc_y, add_y
sinus_add1+=0.32 * delta
sinus_add2+=0.16 * delta
sinus_wwidth1=15+14*sin( sinus_add2 * DEGREES )
sinus_wwidth2=15+14*cos( sinus_add1 * DEGREES )
add_y=0.83*sin( sinus_add1 * DEGREES )
wwidth2=dest->wwidth2
for scanline_y=0 to dest->height-1
sinus=sin(( scanline_y - sinus_add2 ) * DEGREES )*sinus_wwidth1 + cos(( scanline_y+sinus_add1 )*DEGREES )*sinus_wwidth2
x1=wwidth2+sinus+( bar_wwidth * sin(( sinus_add1+ inc_y ) * DEGREES ))
x2=wwidth2+sinus+( bar_wwidth * sin(( sinus_add1+ 90+inc_y ) * DEGREES ))
x3=wwidth2+sinus+( bar_wwidth * sin(( sinus_add1+180+inc_y ) * DEGREES ))
x4=wwidth2+sinus+( bar_wwidth * sin(( sinus_add1+270+inc_y ) * DEGREES ))
if x2>x1 then
dest_ptr=@dest->pixels[ x1 + scanline_y * dest->wwidth ]
pos_x =0
for x=x1 to x2
*dest_ptr=texture->pixels[ pos_x + scanline_y * texture->wwidth ]
dest_ptr +=1
pos_x +=1
next
end if
if x3>x2 then
dest_ptr=@dest->pixels[ x2 + scanline_y * dest->wwidth ]
pos_x=0
for x=x2 to x3
*dest_ptr=texture->pixels[ pos_x + scanline_y * texture->wwidth ]
dest_ptr +=1
pos_x+=1
next
end if
if x4>x3 then
v=(x4-x3) '* 2
colour=rgb(v,0,v)
for x=x3 to x4
dest->pixels[ x+scanline_y*dest->wwidth ]=colour
next
end if
if x1>x4 then
v=(x1-x4) '*2
colour=rgb(0,v,0)
for x=x4 to x1
dest->pixels[ x+scanline_y*dest->wwidth ]=colour
next
end if
inc_y+=add_y
next
end sub
function create_graphics_buffer( byval wwidth as integer, byval height as integer ) as graphics_buffer ptr
dim as graphics_buffer ptr buffer=callocate(len(graphics_buffer)+len(uinteger)*wwidth*height)
buffer->wwidth = wwidth
buffer->height = height
buffer->wwidth2= wwidth \ 2
buffer->height2= height \ 2
buffer->pixels = cast( uinteger ptr, cast( byte ptr, buffer )+len(graphics_buffer))
return buffer
end function
function graphics( byval title as string, byval wwidth as integer, byval height as integer, byval options as integer=0 ) as graphics_buffer ptr
if options=0 then
ptc_setdialog(1,"would you prefer full screen dude?",0,0)
else
ptc_setdialog(0,"",0,1)
end if
ptc_allowclose(1)
if ( ptc_open ( title, wwidth, height ) = 0 ) then
end -1
end if
return create_graphics_buffer(wwidth,height)
end function
Cheers heaps,
Clyde.
-
EXE please for people who cant be bothered to upgrade FB :) Thanks!
-
EXE please for people who cant be bothered to upgrade FB
And for people who do not use FB at all, just so we can see whats going on and perhaps comment on what could be wrong.
-
Your texture is 128 pixels wide.
You're copying it 1:1 into each scanline.
But your scanline might be longer than 128 pixels.
Instead you want to scale your texture to match the scanline's length.
Exe attached.
-
for those without freebasic + latest improvements in the last update, humble appologies. I didnt want to post an exe incase of out of bounds errors, and for quickness.
Cheers Hellfire, i've mucked about with it, and am not sure where I should be using the scaleing, I know it involves dividing the wwidth by the texture->wwidth. Just wondered dude, if you could point me in the right direction. And thankyou for uploading an executable. Really appreciate it!
Cheers and have a good one,
Clyde.
-
You simply map [0..scanLength] to [0..textureWidth]:
dim as len= (x2-x1)
for x=0 to len-1
dest_ptr[x]= texture->pixels[ (x*texture->wwidth/len) + scanline_y * texture->wwidth ]
nextOf course you should use some sort of fixed-point interpolation to avoid divisions and float/int-casts.
-
Just a note that you may already know. You can use -exx in the compile command line and it will print out any out of bound errors or bad pointers. I always use -exx during development since it is quite easy to miss these sort of things; FB will just ignore the error without -exx and often times produce very strange, hard-to-figure-out results.
-
Cheers x 2 :)
if x2>x1 then
dim length as integer =int(x2-x1)
dest_ptr=@dest->pixels[ int(x1) + int(scanline_y) * dest->wwidth ]
for pos_x=0 to length-1
*dest_ptr=texture->pixels[ (pos_x * (texture->wwidth\length)) + (scanline_y) * texture->wwidth ]
dest_ptr +=1
next
end if
this isnt quite there.
-
Imagine "length" is 67 and "texture->wwidth" is 128.
To get from [0..67] to [0..128] you would multiply "pos_x" by 1.91.
Since you calculated the factor using an integer division it's rounded to 1.0 and you're ending up on a wrong coordinate, so
pos_x * (texture->wwidth\length)should be
(pos_x * texture->wwidth)\length
A better option would be something like this
dim as integer u = 0
dim as integer deltau = (texture->wwidth shl 16) \ length
dim as uinteger ptr src = texture->pixels + y * texture->wwidth
for x = 0 to length-1
dest[x]= src[ u shr 16 ]
u+=deltau
next
On very limited hardware you would even precalculate all possible combinations of scaled scanlines and just display the right bitmap.
-
fantastico! thanks mate, I'll try the 2nd option in ze morning.
-
for some reason it misses off 1 to 2 pixels from the right hand edge.
if x2>x1 then
length=int(x2-x1)
dest_ptr=@dest->pixels[ int(x1) + (scanline_y) * dest->wwidth ]
for pos_x=0 to length-1
dim as integer pos_xx=( pos_x*(texture->wwidth)\length)
*dest_ptr=texture->pixels[ ( pos_xx )+(scanline_y)*texture->wwidth ]
dest_ptr +=1
next
end if
really appreciate it,
Clyde.
-
pos_xx=( pos_x*(texture->wwidth)length)
???
-
Oops thats a typo, should be a divide '\' before length.
- edit -I'll upload a new version in just a tick, ive noticed that for some reason a right slanting or integer divide sign doesnt show up in messages.
-
Test /
/
-
Here's an update version w\ image file + source + exe.
Notice the right hand side of the bar twister.
I call it a texture in it, it is an image that could be anything, not neccassarily powers of two; in this the image width is 128, height as tall as the screen resolution height. i dont know if the mod 4 part in the clyde - graphics 2d.bas would muck things about.
thankyou in advance,
Clyde.
-
I'm not quite sure what your problem is.
In "setup_shades" you're setting the two left- and right-most pixels of your texture to white and both appear on the twister.
Of course certain texels are skipped but that's the concept of scaling...
type graphics_buffer
as integer wwidth, height
as integer wwidth2, height2
as uinteger ptr pixels
end type
dim as graphics_buffer ptr buffer = callocate(len(graphics_buffer)+len(uinteger)*wwidth*height)
buffer->pixels = cast( uinteger ptr, cast( byte ptr, buffer)+len(graphics_buffer))
This (http://freeworld.thc.org/root/phun/unmaintain.html) might be interesting for you ;)
-
Apart from writting unmaintainable code. the whole width of the texture per panel or side of the bar, isnt being drawn quite correctly. and the white edging is there to make it stand out more, when you run it.
-
What I do sometimes when something just isn't working as I want it to, is to take my knowledge of how it is supposed to work and then write the code again from scratch.
Break the effect down in small parts, plan what variables, arrays, etc is needed for each part, put those into code, document it, and then start putting the code together one function at a time, one line at a time. It will often also make the code more clear and easy to deal with.
Not sure if you want to spend time on doing so, but it has helped me previously doing so and it might help you.
Also always try and make code reusable, which it why its important to break things down in smaller parts. That way you only have to write code that does various things once, and can reuse it later for something else. Keep functions self contained so that they only need input from outside via parameters and does not depend too much on global variables, arrays and such.
Just a couple of tips that I though of that might assist you in getting on with the effect. As far as the actual code you already have, I don't really have much that I can help with. Its a long while since I dropped FB, and I haven't really kept up with the syntax and such.
But it does sound like you still have some problems with your interpolation math.
-
the whole width of the texture per panel or side of the bar, isnt being drawn quite correctly
You mean the white border shouldn't disappear when the scanlines get smaller at the sides?
When a scanline is eg. 16 pixels wide, you're only plotting every 8th pixel from your texture and the two white border-pixels might fall somewhere in between.
The solution for this problem is to use prefiltered mipmaps and/or filtering.
Another problem is missing perspective. That would require a completely different approach, though.
-
You mean the white border shouldn't disappear when the scanlines get smaller at the sides?
Exactly dude. I could put in a key to pause each screen update, so it's easier to see.
i'll look back and do some interpolating stuff. i thought there might be a simplish fix, as it's only the last few pixels, and maybe i'd not got the x interpolating not bang on. at first i thought it was easy as just drawing a line from x1-x2 etc. good old gouraud shading me thinks.
Thanks,
Clyde.
-
I just want to say too, that even though you may get bored seeing me asking for a hand.
Actually I wish there were more people asking for help here.
i thought there might be a simplish fix, as it's only the last few pixels
It's indeed simple to fix "the last few pixels".
There's no problem on the the left border because you're always starting with the left-most pixel in the texture.
So you just have to make sure that the last pixel of a scanline adresses the right-most pixel in the texture:
pos_xx=( pos_x*(texture->wwidth-1)\(length-1))
-
[...off topic...]
This (http://freeworld.thc.org/root/phun/unmaintain.html) might be interesting for you ;)
Haha, very funny reading this :)
[.../off topic...]
-
[...off topic...]
This (http://freeworld.thc.org/root/phun/unmaintain.html) might be interesting for you ;)
Haha, very funny reading this :)
[.../off topic...]
lol, I second this! awesome stuff :P