Page 2 of 9

Posted: Mon Jun 20, 2005 9:59 am
by MrMat
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!

Posted: Mon Jun 20, 2005 5:51 pm
by Dreglor
ok, i changed the values to these
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
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.

Code: Select all

radius.f=*Sphere\radius
c.f=(Pow(Originx-Spherex,2)+Pow(Originy-Spherey,2)+Pow(Originz-Spherez,2))-Pow(radius,2) 

Posted: Mon Jun 20, 2005 6:24 pm
by MrMat
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!):

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()
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!

Posted: Mon Jun 20, 2005 8:09 pm
by Dreglor
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

Posted: Mon Jun 20, 2005 8:23 pm
by MrMat
Glad to help :)

For a speed increase it might be faster to replace the Pow(x,2) lines with x*x (if it is then perhaps the compiler should do that for us!). The RGB's could be calculated once outside the loop instead and the plots could be done directly to screen memory.

Posted: Mon Jun 20, 2005 8:50 pm
by MrMat
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

Posted: Mon Jun 20, 2005 9:05 pm
by Dreglor
wow your fast, i was just to post my own optimaztion that did exactly what yours did :)

there are a few small harder opimzations i could do like drawing buffer it may not work in windowed mode though

Posted: Mon Jun 20, 2005 9:10 pm
by MrMat
hehe, i'll leave you to make any further optimisations! It feels like a game of Elite at the moment!

Posted: Tue Jun 21, 2005 3:25 am
by Dreglor
Let There Be Light! :D
Image
the code is a real mess right now though :\

Posted: Tue Jun 21, 2005 10:17 am
by MrMat
Wow that looks great! Is it fast?

Posted: Tue Jun 21, 2005 1:14 pm
by remi_meier
Just a question: Did you read DarkDragon's first post?

Posted: Tue Jun 21, 2005 1:22 pm
by MrMat
Yes! The screenshots in the German forum look great. Alas i can't read a word of it but it looks like they're doing some awesome stuff :)

Posted: Tue Jun 21, 2005 1:29 pm
by remi_meier
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 :wink:

Posted: Tue Jun 21, 2005 1:31 pm
by MrMat
Thanks for the link Remi! It's great theres so much interest in such a fun area of computer graphics :D

Posted: Tue Jun 21, 2005 8:56 pm
by Dreglor
yeah i saw that to bad it doesn't have its source :\

well the with the lighting its 20fps
with out it's 40fps

the lighting is directional it not a point light yet

right now im am working on a system to incorperate muiltible objects with diffrent types