Dark Bit Factory & Gravity
PROGRAMMING => Freebasic => Topic started 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
' 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
-
maybe it's because of mixing floats with integers.
should this look like a chessboard?
-
Yes, I've just tried to isolate 1 position on the x axis
-
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.
-
I thought as much.
So what would be the best / easiest way to calculate true "parallax" points?
-
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).
-
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?
-
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 :)
-
I am not able to work out how far apart they should be etc.
What exactly is the problem?
-
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
-
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 ).
-
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
-
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).
-
Sorry to sound thick, but can you demonstrate on that first piece of code :)
-
This probably it's not what you want Nzo, but it might be useful for something else.
I just changed this line:
r=(u And 255)to
r=(u And 256)
#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
-
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:
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
-
Riiiiight :)
Now I see what you mean... duh
Splendid.. thanks a lot for putting up with my stupidness!
-
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.
-
Even better !
Now you can see where this is going :)
K++
-
Yeah ... copperbar - madness!
Good co-op work, mates!
-
very pretty!
Jim
-
Great job mate :clap:
-
http://www.dbfinteractive.com/forum/index.php/topic,2816.msg38767/topicseen.html#msg38767
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).
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.
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
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...
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