Dark Bit Factory & Gravity

PROGRAMMING => Freebasic => Topic started by: Clyde on January 24, 2010

Title: Twister Texturing
Post 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.
 
Code: [Select]
' 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.
Title: Re: Twister Texturing
Post by: Shockwave on January 26, 2010
EXE please for people who cant be bothered to upgrade FB :) Thanks!
Title: Re: Twister Texturing
Post by: zawran on January 27, 2010
Quote
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.
Title: Re: Twister Texturing
Post by: hellfire on January 27, 2010
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.
Title: Re: Twister Texturing
Post by: Clyde on January 27, 2010
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.
Title: Re: Twister Texturing
Post by: hellfire on January 27, 2010
You simply map [0..scanLength] to [0..textureWidth]:
Code: [Select]
dim as len= (x2-x1)
for x=0 to len-1
  dest_ptr[x]= texture->pixels[ (x*texture->wwidth/len) + scanline_y * texture->wwidth ]
next
Of course you should use some sort of fixed-point interpolation to avoid divisions and float/int-casts.
Title: Re: Twister Texturing
Post by: rdc on January 27, 2010
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.
Title: Re: Twister Texturing
Post by: Clyde on January 27, 2010
Cheers x 2 :)

Code: [Select]
    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.
Title: Re: Twister Texturing
Post by: hellfire on January 27, 2010
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
Code: [Select]
pos_x * (texture->wwidth\length)should be
Code: [Select]
(pos_x * texture->wwidth)\length
A better option would be something like this
Code: [Select]
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.
Title: Re: Twister Texturing
Post by: Clyde on January 27, 2010
fantastico! thanks mate, I'll try the 2nd option in ze morning.
Title: Re: Twister Texturing
Post by: Clyde on January 29, 2010
for some reason it misses off 1 to 2 pixels from the right hand edge.

Code: [Select]
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.
Title: Re: Twister Texturing
Post by: hellfire on January 29, 2010
Quote
Code: [Select]
pos_xx=( pos_x*(texture->wwidth)length)
???
Title: Re: Twister Texturing
Post by: Clyde on January 29, 2010
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.
Title: Re: Twister Texturing
Post by: Shockwave on January 29, 2010
Test  /
Code: [Select]
/
Title: Re: Twister Texturing
Post by: Clyde on January 29, 2010
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.
Title: Re: Twister Texturing
Post by: hellfire on January 29, 2010
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...

Quote
Code: [Select]
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  ;)
Title: Re: Twister Texturing
Post by: Clyde on January 29, 2010
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.
Title: Re: Twister Texturing
Post by: zawran on January 29, 2010
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.
Title: Re: Twister Texturing
Post by: hellfire on January 29, 2010
Quote
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.
Title: Re: Twister Texturing
Post by: Clyde on January 29, 2010
Quote from: hellfire
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.
Title: Re: Twister Texturing
Post by: hellfire on January 29, 2010
Quote
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.

Quote
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:
Code: [Select]
pos_xx=( pos_x*(texture->wwidth-1)\(length-1))
Title: Re: Twister Texturing
Post by: Rbz on January 31, 2010
[...off topic...]
This (http://freeworld.thc.org/root/phun/unmaintain.html) might be interesting for you  ;)
Haha, very funny reading this :)

[.../off topic...]
Title: Re: Twister Texturing
Post by: neriakX on October 21, 2011
[...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