RayTracer Theory and Practice
In TestSphere the first 9 variables should be floats instead of longs. There is no need to calculate a (it is always 1 since the direction is normalised). I think C should have the radius of the sphere squared subtracted from it (although they appear to have missed it out on the DevMaster site). Also you need to set the position/radius of the Test sphere. It should work then!
Mat
ok, i changed the values to these
and changed the type to float on those nine values
then used
and i add the squared radius into C like you said and it worked kinda werid though with certain values
it is as big as i can get it before i get negitive values (inside?)
i also put in radius in there.
and changed the type to float on those nine values
then used
Code: Select all
Test\center\x=0
Test\center\y=0
Test\center\z=0
Test\radius=5.989
Origin\x=0
Origin\y=0
Origin\z=-6
Direction\x=x
Direction\y=y
Direction\z=6
it is as big as i can get it before i get negitive values (inside?)
i also put in radius in there.
Code: Select all
radius.f=*Sphere\radius
c.f=(Pow(Originx-Spherex,2)+Pow(Originy-Spherey,2)+Pow(Originz-Spherez,2))-Pow(radius,2)
~Dreglor
Sorry i missed there's a bug in the VectorNormalize procedure. The 3 "If *this\x < #Tolarance" lines should have Abs() around the *this\x. I think you've left the a's in (you can replace them with 1) in the TestSphere procedure (the normalise bug didn't show up with the a removed so i missed it earlier).
Here's what i'm running (sorry i fiddled with some formatting/spelling in your code!):
There's a possibility the TestSphere procedure could return the incorrect value because if D>0 the return value could be negative but apart from that i think it's working ok!
Here's what i'm running (sorry i fiddled with some formatting/spelling in your code!):
Code: Select all
#ScreenWidth=320
#ScreenHeight=240
#Tolerance=0.0001
Structure xyz
x.f
y.f
z.f
EndStructure
Structure Sphere
center.xyz
radius.f
EndStructure
Procedure VectorNormalize(*this.xyz)
m.f = Sqr(*this\x * *this\x + *this\y * *this\y + *this\z * *this\z)
If m < =#Tolerance
m = 1
Else
*this\x = *this\x / m
*this\y = *this\y / m
*this\z = *this\z / m
EndIf
If Abs(*this\x) < #Tolerance
*this\x = 0
EndIf
If Abs(*this\y) < #Tolerance
*this\y = 0
EndIf
If Abs(*this\z) < #Tolerance
*this\z = 0
EndIf
EndProcedure
Procedure.f TestSphere(*Direction.xyz,*Origin.xyz,*Sphere.Sphere)
dirx.f=*Direction\x
diry.f=*Direction\y
dirz.f=*Direction\z
Originx.f=*Origin\x
Originy.f=*Origin\y
Originz.f=*Origin\z
Spherex.f=*Sphere\center\x
Spherey.f=*Sphere\center\y
Spherez.f=*Sphere\center\z
Sphererad.f=*Sphere\radius
b.f=2*(dirx*(Originx-Spherex)+diry*(Originy-Spherey)+dirz*(Originz-Spherez))
c.f=Pow(Originx-Spherex,2)+Pow(Originy-Spherey,2)+Pow(Originz-Spherez,2)-Pow(Sphererad,2)
D.f=Pow(b,2)-4*c
If D>0 ;hit the sphere
t.f=(-b - Sqr(D)) / 2 ; Could return +ve or -ve number!
ElseIf D=0 ;glazing the sphere
t.f=-1
ElseIf D<0 ;missed completely
t.f=-2
EndIf
ProcedureReturn t
EndProcedure
Origin.xyz
Direction.xyz
Testing.Sphere
Testing\center\x=0
Testing\center\y=0
Testing\center\z=100
Testing\radius=100
Origin\x=0
Origin\y=0
Origin\z=-256
InitSprite()
OpenWindow(0,0,0,#ScreenWidth,#ScreenHeight,#PB_Window_ScreenCentered|#PB_Window_SystemMenu,"Ray Test")
StartDrawing(WindowOutput())
Repeat
For y=-#ScreenHeight/2 To (#ScreenHeight/2)-1 Step 1
For x=-#ScreenWidth/2 To (#ScreenWidth/2)-1 Step 1
Direction\x=x
Direction\y=y
Direction\z=256
VectorNormalize(Direction)
t.f=TestSphere(Direction,Origin,Testing)
posx=x+(#ScreenWidth/2)
posy=y+(#ScreenHeight/2)
If t>0 ; Red - Hit (object has +ve parameter t)
Plot(posx,posy,RGB(255,0,0))
ElseIf t=-1 ; Green - Glazing; Could be returned incorrectly (when (-b - Sqr(D)) / 2 = -1)
Plot(posx,posy,RGB(0,255,0))
ElseIf t=-2 ; Blue - Missed; Could be returned incorrectly (when (-b - Sqr(D)) / 2 = -2)
Plot(posx,posy,RGB(0,0,255))
Else ; White - Hit (object has -ve parameter t)
Plot(posx,posy,RGB(255,255,255))
EndIf
Next x
Next y
Origin\z + 10
Until WindowEvent()=#PB_Event_CloseWindow
StopDrawing()
Mat
Awsome thanks for picking that out mrmat 
now i just know that if test sphere returns a negitive it's behind the origin
now i need lighting and reflections/refactions and it will become a simple raytracer
i do notice that the intersection code it pretty fast right now i wonder if its the drawing part thats really slowing it down ?
edit : i did some quick tests and the drawing add quite a bit
rendering a 800x600 window with windowoutput() renders 1750ms
with out the drawing code its 950ms thats 800ms diffrence
im sure i can speed that up though

now i just know that if test sphere returns a negitive it's behind the origin
now i need lighting and reflections/refactions and it will become a simple raytracer
i do notice that the intersection code it pretty fast right now i wonder if its the drawing part thats really slowing it down ?
edit : i did some quick tests and the drawing add quite a bit
rendering a 800x600 window with windowoutput() renders 1750ms
with out the drawing code its 950ms thats 800ms diffrence
im sure i can speed that up though
~Dreglor
It seems a lot faster now. I think it was plotting to a windowed screen that made the biggest difference:
Code: Select all
#ScreenWidth = 320
#ScreenHeight = 240
#Tolerance = 0.0001
Structure xyz
x.f
y.f
z.f
EndStructure
Structure Sphere
center.xyz
radius.f
EndStructure
Procedure VectorNormalize(*this.xyz)
m.f = Sqr(*this\x * *this\x + *this\y * *this\y + *this\z * *this\z)
If m < = #Tolerance
m = 1
Else
*this\x = *this\x / m
*this\y = *this\y / m
*this\z = *this\z / m
EndIf
If Abs(*this\x) < #Tolerance
*this\x = 0
EndIf
If Abs(*this\y) < #Tolerance
*this\y = 0
EndIf
If Abs(*this\z) < #Tolerance
*this\z = 0
EndIf
EndProcedure
Procedure.f TestSphere(*Direction.xyz,*Origin.xyz,*Sphere.Sphere)
offx.f = *Origin\x - *Sphere\center\x
offy.f = *Origin\y - *Sphere\center\y
offz.f = *Origin\z - *Sphere\center\z
Sphererad.f = *Sphere\radius
b.f = 2 * (*Direction\x * offx + *Direction\y * offy + *Direction\z * offz)
c.f = offx * offx + offy * offy + offz * offz - Sphererad * Sphererad
D.f = b * b - 4 * c
If D > 0 ;hit the sphere
t.f = (-b - Sqr(D)) / 2 ; Could return +ve or -ve number!
ElseIf D = 0 ;glazing the sphere
t.f = -1
ElseIf D < 0 ;missed completely
t.f = -2
EndIf
ProcedureReturn t
EndProcedure
Origin.xyz
Direction.xyz
Testing.Sphere
Testing\center\x=0
Testing\center\y=0
Testing\center\z=100
Testing\radius=100
Origin\x=0
Origin\y=0
Origin\z=-512
InitSprite()
OpenWindow(0,0,0,#ScreenWidth,#ScreenHeight,#PB_Window_ScreenCentered|#PB_Window_SystemMenu,"Ray Test")
OpenWindowedScreen(WindowID(),0,0,#ScreenWidth,#ScreenHeight,1,0,0)
col1 = RGB(255,0,0)
col2 = RGB(0,255,0)
col3 = RGB(0,0,255)
col4 = RGB(255,255,255)
halfheight = #ScreenHeight/2
halfwidth = #ScreenWidth/2
Repeat
ClearScreen(0, 0, 255)
StartDrawing(ScreenOutput())
For y = -halfheight To halfheight - 1
For x = -halfwidth To halfwidth - 1
Direction\x = x
Direction\y = y
Direction\z = 256
VectorNormalize(Direction)
t.f = TestSphere(Direction, Origin, Testing)
posx = x + halfwidth
posy = y + halfheight
If t>0 ; Red - Hit (object has +ve parameter t)
Plot(posx, posy, col1)
ElseIf t=-1 ; Green - Glazing; Could be returned incorrectly (when (-b - Sqr(D)) / 2 = -1)
Plot(posx, posy, col2)
ElseIf t=-2 ; Blue - Missed; Could be returned incorrectly (when (-b - Sqr(D)) / 2 = -2)
;Plot(posx, posy, col3)
Else ; White - Hit (object has -ve parameter t)
Plot(posx, posy, col4)
EndIf
Next x
Next y
Origin\z + 10
StopDrawing()
FlipBuffers()
Until WindowEvent() = #PB_Event_CloseWindow
Mat
-
- Enthusiast
- Posts: 468
- Joined: Sat Dec 20, 2003 6:19 pm
- Location: Switzerland
-
- Enthusiast
- Posts: 468
- Joined: Sat Dec 20, 2003 6:19 pm
- Location: Switzerland
Just asked because Blade said "Never seen a PB example..."
NicTheQuick has released a raytracing Userlib
http://mitglied.lycos.de/NicTheQuick198 ... 0RTEngine/
so you can test a little bit with the source code. He didn't release the source
of the engine because he probably wants to make money with it. But you
surely can ask him for some tips
NicTheQuick has released a raytracing Userlib
http://mitglied.lycos.de/NicTheQuick198 ... 0RTEngine/
so you can test a little bit with the source code. He didn't release the source
of the engine because he probably wants to make money with it. But you
surely can ask him for some tips

Athlon64 3700+, 1024MB Ram, Radeon X1600