Author Topic: Twister Texturing  (Read 10769 times)

0 Members and 1 Guest are viewing this topic.

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Twister Texturing
« 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.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17412
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Twister Texturing
« Reply #1 on: January 26, 2010 »
EXE please for people who cant be bothered to upgrade FB :) Thanks!
Shockwave ^ Codigos
Challenge Trophies Won:

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: Twister Texturing
« Reply #2 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.

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Twister Texturing
« Reply #3 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.
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Twister Texturing
« Reply #4 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.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Twister Texturing
« Reply #5 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.
Challenge Trophies Won:

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: Twister Texturing
« Reply #6 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.

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Twister Texturing
« Reply #7 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.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Twister Texturing
« Reply #8 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.
« Last Edit: January 27, 2010 by hellfire »
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Twister Texturing
« Reply #9 on: January 27, 2010 »
fantastico! thanks mate, I'll try the 2nd option in ze morning.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Twister Texturing
« Reply #10 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.
« Last Edit: January 29, 2010 by cLYdE »
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Twister Texturing
« Reply #11 on: January 29, 2010 »
Quote
Code: [Select]
pos_xx=( pos_x*(texture->wwidth)length)
???
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Twister Texturing
« Reply #12 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.
« Last Edit: January 29, 2010 by cLYdE »
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17412
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Twister Texturing
« Reply #13 on: January 29, 2010 »
Test  /
Code: [Select]
/
Shockwave ^ Codigos
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Twister Texturing
« Reply #14 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.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Twister Texturing
« Reply #15 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 might be interesting for you  ;)
« Last Edit: January 29, 2010 by hellfire »
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Twister Texturing
« Reply #16 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.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: Twister Texturing
« Reply #17 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.

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Twister Texturing
« Reply #18 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.
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Twister Texturing
« Reply #19 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.
« Last Edit: January 29, 2010 by cLYdE »
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won: