-- start of quote --
Hey everyone :)
I'm currently working on a raytracer engine. I already coded one which worked but it was far from well designed. So I started a new one to handle scene better.
The problem is it doesn't raytrace the only sphere I added to the scene. I'm totally stuck right now, I looked everywhere in the code and I don't get why and where it don't work. Here is the code :
Code: Select all
''
'' Raytracer
''
#include "vector.bi"
Const PRECISION = .1
Const MAX_RAY_LENGTH = 100
Const MAX_PRIMITIVES = 20
Const MAX_LIGHTS = 10
Const PRIM_SPHERE = 1
Const PRIM_PLANE = 2
Type ColorT
as single r,g,b
End Type
Type MaterialT
as ColorT Diffuse,BaseColor
End type
Type Ray
as vector O,d
as single x,y,z,t
Declare Sub Update()
Declare Function Lengthpow2() as single
End Type
Function Ray.Lengthpow2() as single
return (this.x-this.O.x)*(this.x-this.O.x) + (this.y-this.O.y)*(this.y-this.O.y) + (this.z-this.O.z)*(this.z-this.O.z)
End Function
Sub Ray.Update()
this.x = this.O.x + this.d.x*this.t
this.y = this.O.y + this.d.y*this.t
this.z = this.O.z + this.d.z*this.t
this.t += PRECISION
End Sub
Type Primitive
as integer TypeFlag
as MaterialT Material
'' for planes
as single A,B,C,D
'' for spheres
as single R, x,y,z
'' functions
Declare function GetNormal(CRay as Ray) as Vector
Declare function GetIntersection(CRay as Ray) as integer
End type
Function Primitive.GetIntersection(CRay as Ray) as integer
Select case This.TypeFlag
Case PRIM_SPHERE
if (this.x - CRay.x)*(this.x - CRay.x) + (this.y - CRay.y)*(this.y - CRay.y) + (this.z - CRay.z)*(this.z - CRay.z) <= R*R + PRECISION then
return 1
else
return 0
end if
Case PRIM_PLANE
if (this.A*CRay.x + this.B*CRay.y + this.C*CRay.z - this.D < PRECISION) and (this.A*CRay.x + this.B*CRay.y + this.C*CRay.z - this.D > -PRECISION) then
return 1
else
return 0
end if
End Select
End Function
Function Primitive.GetNormal(CRay as Ray) as Vector
static as Vector normal
Select case This.TypeFlag
Case PRIM_SPHERE
normal.x = CRay.x - this.x
normal.y = CRay.y - this.y
normal.z = CRay.z - this.z
Normalize(normal)
return normal
Case PRIM_PLANE
normal.x = -A
normal.y = -B
normal.z = -C
Normalize(Normal)
return normal
End Select
End Function
Type LightT
as single x,y,z
as ColorT l_color
end type
Type SceneT
as Primitive ptr s_Primitive
as integer nb_primitives
as LightT ptr s_light
as integer nb_lights
Declare Constructor()
Declare Destructor()
Declare Sub Add_Sphere(cx as single, cy as single,cz as single, cR as single, Mat as MaterialT)
Declare Sub Add_Plane (cA as single, cB as single,cC as single, cD as single, Mat as MaterialT)
Declare Sub Add_Light(cx as single, cy as single, cz as single,col as ColorT)
End Type
Sub SceneT.Add_Light(cx as single, cy as single, cz as single,col as ColorT)
if this.nb_lights>=MAX_LIGHTS then exit sub
this.s_light[this.nb_lights].x = cx
this.s_light[this.nb_lights].y = cy
this.s_light[this.nb_lights].z = cz
this.s_light[this.nb_lights].l_color = col
this.nb_lights += 1
end sub
Sub SceneT.Add_Sphere(cx as single, cy as single,cz as single, cR as single, Mat as MaterialT)
If this.nb_primitives >= MAX_PRIMITIVES then exit sub
this.s_primitive[this.nb_primitives].typeflag = prim_sphere
this.s_primitive[this.nb_primitives].x = cx
this.s_primitive[this.nb_primitives].y = cy
this.s_primitive[this.nb_primitives].z = cz
this.s_primitive[this.nb_primitives].R = cR
this.s_primitive[this.nb_primitives].Material = Mat
this.nb_primitives += 1
end sub
Sub SceneT.Add_Plane(cA as single, cB as single,cC as single, cD as single, Mat as MaterialT)
If this.nb_primitives >= MAX_PRIMITIVES then exit sub
this.s_primitive[this.nb_primitives].typeflag = prim_plane
this.s_primitive[this.nb_primitives].A = cA
this.s_primitive[this.nb_primitives].B = cB
this.s_primitive[this.nb_primitives].C = cC
this.s_primitive[this.nb_primitives].D = cD
this.s_primitive[this.nb_primitives].Material = Mat
this.nb_primitives += 1
end sub
Constructor SceneT()
this.s_Primitive = Callocate(MAX_PRIMITIVES,Sizeof(Primitive))
this.s_light = Callocate(MAX_LIGHTS,Sizeof(LightT))
End Constructor
Destructor SceneT()
deallocate(this.s_Primitive)
deallocate(this.s_light)
End Destructor
'' main loop
Dim as SceneT Scene
Dim as MaterialT sphereMat
SphereMat.Diffuse = type(.8,.7,.75)
SphereMat.BaseColor = type(.8,.8,.8)
Scene.Add_Light(-5,5,-5,type(1,1,1))
Scene.Add_Sphere(0,2,5,3,SphereMat)
Screenres 640,480,32,2
'' send ray
Dim as Ray MainRay
Dim as integer IntersectedPrimitive
For j as integer = 0 to 479
For i as integer = 0 to 639
MainRay.O = type( 0, 0, -5 )
MainRay.d = type( i-320, j-240,150)
Normalize(MainRay.d)
intersectedprimitive = -1
Do
MainRay.update()
If MainRay.z > 0 then
For k as integer = 0 to Scene.nb_primitives-1
if Scene.s_primitive[k].GetIntersection(MainRay) then
IntersectedPrimitive = k
pset(i,j),rgb(255,255,255)
exit do
End If
next
end if
Loop until MainRay.Lengthpow2 >= MAX_RAY_LENGTH*MAX_RAY_LENGTH
'' calc color !
if intersectedprimitive <> -1 then
static as ColorT MatCol = type(0,0,0)
for k as integer = 0 to scene.nb_lights - 1
static as Vector N, L
static as single dotted
L = type(Scene.s_light[k].x,Scene.s_light[k].y,Scene.s_light[k].z) - Type(MainRay.x,MainRay.y,MainRay.z)
Normalize(L)
N = Scene.s_primitive[intersectedprimitive].GetNormal(MainRay)
dotted = dot(N,L)
if dotted > 0 then
MatCol.r += dotted * Scene.s_primitive[intersectedprimitive].Material.Diffuse.r * Scene.s_primitive[intersectedprimitive].Material.BaseColor.r * Scene.s_light[k].l_color.R
MatCol.g += dotted * Scene.s_primitive[intersectedprimitive].Material.Diffuse.g * Scene.s_primitive[intersectedprimitive].Material.BaseColor.g * Scene.s_light[k].l_color.G
MatCol.b += dotted * Scene.s_primitive[intersectedprimitive].Material.Diffuse.b * Scene.s_primitive[intersectedprimitive].Material.BaseColor.b * Scene.s_light[k].l_color.B
end if
next
Pset(i,j),rgb(MatCol.r*255, MatCol.G*255,MatCol.b*255)
else
Pset(i,j),rgb(25,25,25)
end if
next
next
sleep
Code: Select all
Do
MainRay.update()
If MainRay.z > 0 then
For k as integer = 0 to Scene.nb_primitives-1
if Scene.s_primitive[k].GetIntersection(MainRay) then
IntersectedPrimitive = k
pset(i,j),rgb(255,255,255)
exit do
End If
next
end if
Loop until MainRay.Lengthpow2 >= MAX_RAY_LENGTH*MAX_RAY_LENGTH
I replaced pointers with arrays but it didn't change anything, I checked and checked again the intersection functions, the ray.update() function but everything looks okay to me ..
Does anyone have an idea of what's wrong here ?
Thanks a lot in advance :)
(oh and here is the vector.bi file if you want to compile this code :
Code: Select all
''
'' Vectors Library
'' for raytracer
''
Type Vector
as single x,y,z
End Type
Operator +(L as Vector, R as Vector) as Vector
return type(L.x+R.x,L.y+R.y,L.z+R.z)
End operator
Operator -(L as Vector, R as Vector) as Vector
return type(L.x-R.x,L.y-R.y,L.z-R.z)
End Operator
Operator *(L as Vector, R as Vector) as Vector
return type( L.y*R.z + L.z*R.y , _
L.z*R.x + L.x*R.z , _
L.x*R.y + L.y*R.x )
End operator
Function Dot(V1 as vector, V2 as vector) as single
return V1.x*V2.x + V1.y*v2.y + v1.z*v2.z
End function
Sub Normalize(ByRef V as Vector)
static as single _norm
_norm = 1/sqr(V.x*v.x + V.y*v.y + v.z*v.z)
V.x *= _norm
V.y *= _norm
V.z *= _norm
End Sub