Dark Bit Factory & Gravity

PROGRAMMING => Freebasic => Topic started by: nzo on August 02, 2010

Title: Floor Casting
Post by: nzo on August 02, 2010
Been struggling with the following (I think I found the idea on here originally)
Want to always have a single value on each line (you can see where the value is anded) but it's not always a straight line. If you uncomment the  ' camX += 0.1 line, you can see it flickering when moving.

Been struggling with this for a bit, so would be very happy if someone can solve this problem for me!!

cheers


Code: [Select]
' Floor Casting
const XRES = 640
const YRES = 480
'const xres = 320
'const yres = 240

#include once "tinyptc.bi"
if (ptc_open("FLOOR CASTING", 640, 480) = 0) then end -1

dim shared as integer buffer(XRES*YRES)
Dim Shared as single u, v, w, camX, camY

 Declare Sub floor()

while (inkey$ = "")
  floor()

  ptc_update@buffer(0)
      ERASE BUFFER

Wend
ptc_close
end 0

Sub floor()
dim as integer c, b, r

  'camY += 1
'  camX += 1 'xres*sin(camY*3.14159/180)
 ' camX += 0.1
  b = 150*XRES
 
  For y = 50 to 200-1
 
    w  = -240 / y
   
    v =  XRES*w - camY
   
    u = -320*w + camX
   
     for x = 1 To XRES-1
r=(u And 255)
Select Case r
Case 0
buffer(b+x) = rgb(255,0,0)
Case Else
buffer(b+x) = rgb(0,0,0)
End Select
'       Else
' buffer(b+x) = rgb(0,0,0)

       'buffer(b+x) = rgb(u And 255,v And 255,0)
       u=u+w
     Next x
   
    b=b+XRES
  Next y

End Sub
Title: Re: Floor Casting
Post by: Storm Trooper on August 02, 2010
maybe it's because of mixing floats with integers.
should this look like a chessboard?
Title: Re: Floor Casting
Post by: nzo on August 03, 2010
Yes, I've just tried to isolate 1 position on the x axis
Title: Re: Floor Casting
Post by: hellfire on August 03, 2010
So your problem are the missing pixels in the lines?
That's because interpolation skips some values (you sometimes just don't catch the "0"-case).
And points in consecutive rows can be further apart than a single pixel (so there will be gaps, too).
After all your algorithm isn't very suitable to draw continuous lines.

Title: Re: Floor Casting
Post by: nzo on August 03, 2010
I thought as much.
So what would be the best / easiest way to calculate true "parallax" points?
Title: Re: Floor Casting
Post by: hellfire on August 03, 2010
So what would be the best / easiest way to calculate true "parallax" points?
Your "points" are ok, they just don't make a continuous line.
To get lines just calculate the x-position of each line in the top row (just skip the black area between two pixels) and the corresponding x-position in the bottom row (which is just scaled at the center of the screen).
Then draw the line using Bresenham (http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm) or Wu (http://en.wikipedia.org/wiki/Xiaolin_Wu%27s_line_algorithm).
Title: Re: Floor Casting
Post by: nzo on August 03, 2010
Thanks for the links.
Trouble is, there isn't always a point to reference. I guess you mean abandon this idea and do it with 2 sets of points; one distant and one close up, draw the lines and look up the set value on each line?
Title: Re: Floor Casting
Post by: nzo on August 03, 2010
Actually, scratch that.
I just tried that out, but in my dimness, still am not able to work out how far apart they should be etc.

I guess I'm just asking for someone to show me :)
Title: Re: Floor Casting
Post by: hellfire on August 03, 2010
I am not able to work out how far apart they should be etc.
What exactly is the problem?
Title: Re: Floor Casting
Post by: nzo on August 03, 2010
Essentially how to calculate flawless parallax effect. Like my original post, but one that actually works.

I guess it's just easier to show you what I`m trying to do... this example still flickers, even with allowing 0-3 as a (masked) value
Title: Re: Floor Casting
Post by: hellfire on August 04, 2010
how to calculate flawless parallax effect.
"Parallax" (http://en.wikipedia.org/wiki/Parallax) means you're moving multiple parallel layers according to their depth - that's exactly what you aready do with every scanline and in fact there's nothing wrong with it.
But if you want lines it just won't work. You can have a look at the case where bresenham distinguishes horizontal and vertical lines to see why.
To get proper lines you need a different approach. But I'm still a little confused what exactly you're trying to achieve as your example shows bars, too...  ???

The easiest way to get continuous lines is to keep track of the positions in the previous scanline and fill the horizontal space between two contiguous points.
Two points in different rows belong to the same line when their "u" have the same "integer part" ( u shr 8 ).
Title: Re: Floor Casting
Post by: nzo on August 04, 2010
The bars are what I'm actually trying for.
The points are just a representation of how the bars are positioned (bar positioned at point on X axis, each layer is on Y axis)
However, i can't trust a specific "point" as it's not always set.
Essentially, I want to know the gap between each point/bar on each line and as I can't be sure where a "point" is from one frame to the next, there's my problem
Title: Re: Floor Casting
Post by: hellfire on August 04, 2010
Now I'm getting it! :D
All you want to know is whether "r" crossed zero while stepping to the next pixel.
Just test if the current "r" is smaller than the "r" from the previous pixel (you can simply store it in another variable).

Title: Re: Floor Casting
Post by: nzo on August 04, 2010
Sorry to sound thick, but can you demonstrate on that first piece of code :)
Title: Re: Floor Casting
Post by: Rbz on August 04, 2010
This probably it's not what you want Nzo, but it might be useful for something else.

I just changed this line:
Code: [Select]
r=(u And 255)to
Code: [Select]
r=(u And 256)
Code: [Select]
#define PTC_WIN

' Floor Casting
const XRES = 640
const YRES = 480
'const xres = 320
'const yres = 240

#include once "tinyptc.bi"
if (ptc_open("FLOOR CASTING", 640, 480) = 0) then end -1

dim shared as integer buffer(XRES*YRES)
Dim Shared as single u, v, w, camX, camY

 Declare Sub floor()

while (inkey$ = "")
  floor()

  ptc_update@buffer(0)
      ERASE BUFFER

Wend
ptc_close
end 0

Sub floor()
dim as integer c, b, r, x, y

  'camY += 1
  camX += 1   'xres*sin(camY*3.14159/180)
 ' camX += 0.1
  b = 150*XRES
 
  For y = 50 to 200-1
     
    w  = -240 / y
   
    v =  XRES*w - camY
   
    u = -320*w + camX
   
     for x = 1 To XRES-1   
     
      r=(u And 256)
         
      Select Case r
         Case 0
          buffer(b+x) = cast(integer,rgb(255,0,0))
         Case Else
          buffer(b+x) = cast(integer,rgb(0,0,120))
      End Select

      u=u+w
             
     Next x
   
    b=b+XRES
  Next y
   
End Sub
Title: Re: Floor Casting
Post by: hellfire on August 05, 2010
Sorry to sound thick, but can you demonstrate on that first piece of code :)
Sure.
This way you won't miss "r=0" when r jumps from eg 254 to 1:
Code: [Select]
Sub floor()
  dim as integer c, b, r, x, y, prer
  camX += 0.1
  b = 150*XRES
 
  For y = 50 to 200-1
    w  = 240 / y
    v =  XRES*w - camY
    u = -320*w + camX
    r= 0
   
    for x = 0 To XRES-1
      prer= r   ' r from previous pixel
      r=(u And 255)
     
      if (r < prer) then
          buffer(b+x) = 255 shl 16
      else
          buffer(b+x) = 0
      end if
     
      u=u+w
    Next x
   
    b=b+XRES
  Next y
   
End Sub
Title: Re: Floor Casting
Post by: nzo on August 05, 2010
Riiiiight :)
Now I see what you mean... duh
Splendid.. thanks a lot for putting up with my stupidness!
Title: Re: Floor Casting
Post by: hellfire on August 05, 2010
Quote
thanks a lot for putting up with my stupidness!
No problem!
You're now testing every single pixel if it's the one you're looking for - that's not a very elegant algorithm.
You already know that you want every 256th pixel at a step-size of "w".
So after you've found the first pixel, the next one will be "256/w" pixels away.
Title: Re: Floor Casting
Post by: nzo on August 05, 2010
Even better !

Now you can see where this is going :)

K++
Title: Re: Floor Casting
Post by: benny! on August 05, 2010
Yeah ... copperbar - madness!

Good co-op work, mates!
Title: Re: Floor Casting
Post by: Jim on August 05, 2010
very pretty!
Jim
Title: Re: Floor Casting
Post by: Dr.Death on August 05, 2010
Great job mate  :clap:
Title: Re: Floor Casting
Post by: rain_storm on October 05, 2010
http://www.dbfinteractive.com/forum/index.php/topic,2816.msg38767/topicseen.html#msg38767

Code: [Select]
    w  = -yres / y
This w variable is a scalar. It is used to set up the scale of each horizontal line (rows). w is proportional to the distance y relative to a fixed point along the y axis I used -yres or half the screen width above the first pixel. The effect of this is that rows which are closer to this point are scaled by a smaller size. The scale is then applied to all pixels contained in that row (a horizontal line).

Code: [Select]
      u = u + w
Here you can see that u is a UV co-ordinate and on each iteration of the inner loop we increment the u co-ordinate by the depth scalar w. By this mechanism the scalar w is applied to each pixel in the row. as the value of y grows larger the increment becomes smaller. to phrase that another way the further away from the fixed point your current row happens to be, the longer it will take for w to increment u such that u is incremented by an integer 1.0

By the time y reaches the bottom of the screen, w is minimal and it takes a long time for it to increment u co-ordinates to the next higher integer.

Code: [Select]
    v =  resX*w - camY
    u = -xres*w + camX

This part of the code is used to add some dynamics to the scene we are simply setting up the initial values for the u and v co-ordinates. we can move the camera up or down by changing v or we can move the camera left and right by changing u. Once these variables have been set up however there is no room to play with them. u must be incremented by w and v must remain unchanged. I think you already gathered this

Code: [Select]
      c = (u xor v) and 255
      buffer(b+x) = rgb(c,c,c)
Here in my code we convert the uv co-ordinates into a checkerboard pattern. This is done by simply taking their integer parts, xoring them, then taking the low 8 bit value to define the color. this part probably needs no further explaination, except that we are only interested in the integer parts of u and v.

so from this info we can see that to do this for just a few arbitrary points what you need to do is...

Code: [Select]
for p = 0 to points
    w  = -yres / pointY(p)
    v = resX*w - camY
    u = (-xres*w + camX) + w*pointX(p)
    pixel u, v
next p

Points can be plotted at will and appear to move uniformly in paralax. Points drawn later will be drawn on top of existing points overwriting them in the process.
pointY can even be replaced by pointZ and you are then free to choose where to plot the pixel on the y axis