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 :
''
'' 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
The point is, I tested the intersection functions with this part :
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
It should draw a white point if the ray intersect the primitive, but it looks like the program skips this part and directly draw the background color ...
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 :
''
'' 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
Hey Hezad,
Is there a reson you are attempting to detect intersections this way?
So you are:
1) calculating the end point of your ray
2) Checking if the endpoint is within the sphere
3) increasing the length of the ray
I would think about the ray differently. A ray has an Origin and a Direction but it has no end point.
Feed that infinate ray into a function that tells you the closest intersection point with the sphere.
Here is some code that checks for a ray to sphere intersection:
Function SphereIntersect(R As RayType, S As SphereType) As IntersectionType
Dim Result as IntersectionType
Dim As VectorType rayToSphereCentre
Dim As Single SquaredDistToCentre, ClosestApproach, HalfCord2
rayToSphereCentre = Vec_Subtract(S.Centre, R.Origin)
SquaredDistToCentre = Vec_DotProduct(rayToSphereCentre, rayToSphereCentre)
ClosestApproach = Vec_DotProduct(rayToSphereCentre, R.Dir)
If ClosestApproach<0 Then
Result.Dist=-1
SphereIntersect = Result
Exit Function
End If
HalfCord2 = (S.Radius * S.Radius) - SquaredDistToCentre + (ClosestApproach * ClosestApproach)
If HalfCord2 < 0 Then
Result.Dist=-1
SphereIntersect = Result
Exit Function
End If
Result.Dist = ClosestApproach - Sqr(Halfcord2)
SphereIntersect = Result
End Function
Thanks for your answer :)
Well right now, I'm "following" the ray to experiment some stuff, but thanks a lot for your intersection function it will be very useful for the next functions :)
Oh, someone on freebasic forums found why my code weren't working : I forgot to initialize the ray time variable to 0 on each loop ><
Some news :) Some huge optimizations (Ray experimentation has ended :P the intersections are now calculated with an algebraic method => HUGE speed improvement :D )
Current problems :
- shadows (the third "line" of spheres has an incorrect shadow)
- phong is wrong : there are highlights on both sides of spheres and that's totally anormal.
- plane intersection is wrong : It's totally impossible to put a plane at another place, it generates very (very very) ugly artefacts
Anyway, here is the code if you wanna take a look at it :)
raytracer :
''
'' Raytracer
''
#include "vector.bi"
Const PRECISION = .1
Const MAX_PRIMITIVES = 200
Const MAX_LIGHTS = 10
Const PRIM_SPHERE = 1
Const PRIM_PLANE = 2
Const MAX_REFLECTIONS = 5
Const CALC_SHADOWS = 1
Type ColorT
as single r,g,b
End Type
Type MaterialT
as ColorT Diffuse, Specular
as single Reflection, Highlight
End type
Type Ray
as vector O,d
as single x,y,z
Declare Sub Update(t as single)
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(t as single)
this.x = this.O.x + this.d.x*t
this.y = this.O.y + this.d.y*t
this.z = this.O.z + this.d.z*t
End Sub
Type Primitive
as integer TypeFlag
as integer LightFlag
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,ByRef returnT as single) as integer
End type
Function Primitive.GetIntersection(CRay as Ray,ByRef returnT as single) as integer
Select case This.TypeFlag
Case PRIM_SPHERE
dim as single a = dot(Cray.d, Cray.d)
dim as single b = 2 * dot((Cray.o - type(this.x,this.y,this.z)),Cray.d )
dim as single c = dot((Cray.o - type(this.x,this.y,this.z)), (Cray.o - type(this.x,this.y,this.z))) - (this.r * this.r)
dim as single disc = b * b - 4 * a * c
if disc < PRECISION then return 0
dim as single distSqrt = sqr(disc)
dim as single q
if b < 0 then
q = (-b - distSqrt)*.5
else
q = (-b + distSqrt)*.5
end if
dim as single t0 = q / a
dim as single t1 = c / q
if t0>t1 then swap t0,t1
if t1 < PRECISION then return 0
if t0 < PRECISION then
returnT = t1
return 1
else
returnT = t0
return 1
end if
Case PRIM_PLANE
dim as single tempT, num, denum
num = (this.A*CRay.O.x + this.B*CRay.O.y + this.C*CRay.O.z + D)
denum = (this.A*CRay.d.x + this.B*CRay.d.y + this.C*CRay.d.z)
TempT = num/denum
if TempT<PRECISION then
return 0
else
returnT = TempT
return 1
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, lightf as integer=0)
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, lightf as integer=0)
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].lightflag = lightf
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
Dim shared as SceneT Scene
Function RayTrace(ByVal R as Ray,ByVal CurReflection as integer = 0) as ColorT
Dim as Ray MainRay
Dim as integer IntersectedPrimitive
dim as single calcT=10000000, oldCalcT=10000000
MainRay = R
intersectedprimitive = -1
For k as integer = 0 to Scene.nb_primitives-1
oldCalcT=calcT
if Scene.s_primitive[k].GetIntersection(MainRay, calcT) then
if oldCalcT>CalcT then
MainRay.Update(calcT)
IntersectedPrimitive = k
end if
End If
next
'' calc Diffuse and specular colors !
if intersectedprimitive <> -1 then
dim as ColorT MatCol = type(0,0,0)
for k as integer = 0 to scene.nb_lights - 1
dim as Vector N, L, V, R
dim as single dotSpec, dotDiff
L = type<vector>(Scene.s_light[k].x,Scene.s_light[k].y,Scene.s_light[k].z) - Type<vector>(MainRay.x,MainRay.y,MainRay.z)
Normalize(L)
N = Scene.s_primitive[intersectedprimitive].GetNormal(MainRay)
V = MainRay.d
R = GetReflectionVector(V,N)
dotDiff = dot(N,L)
dotSpec = dot(R,L)^Scene.s_primitive[intersectedprimitive].Material.Highlight
'' Calculating Shadow
dim as single shade = 1
if CALC_SHADOWS then
dim as single shadowT
dim as Ray ShadowRay
ShadowRay.O = type(MainRay.x,MainRay.y,MainRay.z)
ShadowRay.d = L
for f as integer = 0 to Scene.nb_primitives-1
if (f<>IntersectedPrimitive) and Scene.s_primitive[f].GetIntersection(ShadowRay, ShadowT) then
shade = .1 : ShadowRay.Update(ShadowT) ' : exit for
End If
next
end if
'' Final Color shading
if dotDiff > 0 then
MatCol.r += dotDiff * Scene.s_primitive[intersectedprimitive].Material.Diffuse.r * Scene.s_light[k].l_color.r * shade
MatCol.g += dotDiff * Scene.s_primitive[intersectedprimitive].Material.Diffuse.g * Scene.s_light[k].l_color.g * shade
MatCol.b += dotDiff * Scene.s_primitive[intersectedprimitive].Material.Diffuse.b * Scene.s_light[k].l_color.b * shade
end if
if dotSpec > 0 then
MatCol.r += dotSpec * Scene.s_primitive[intersectedprimitive].Material.Specular.r * Scene.s_light[k].l_color.r * shade
MatCol.g += dotSpec * Scene.s_primitive[intersectedprimitive].Material.Specular.g * Scene.s_light[k].l_color.g * shade
MatCol.b += dotSpec * Scene.s_primitive[intersectedprimitive].Material.Specular.b * Scene.s_light[k].l_color.b * shade
end if
next
'' Calc reflections
if Scene.s_Primitive[intersectedprimitive].Material.reflection > 0 then
If CurReflection < MAX_REFLECTIONS then
Dim as ColorT refCol
Dim as Ray ReflectionRay
Dim as vector refNormal
refNormal = Scene.s_Primitive[intersectedprimitive].GetNormal(MainRay)
ReflectionRay.O = type(MainRay.x,MainRay.y,MainRay.z)
ReflectionRay.d = GetReflectionVector(MainRay.d,refNormal)
Normalize(ReflectionRay.d)
'' !!! Recursion !!!
refcol = Raytrace(ReflectionRay,CurReflection+1)
'' !!! --------- !!!
MatCol.r += Scene.s_Primitive[intersectedprimitive].Material.reflection*refcol.r
MatCol.g += Scene.s_Primitive[intersectedprimitive].Material.reflection*refcol.g
MatCol.b += Scene.s_Primitive[intersectedprimitive].Material.reflection*refcol.b
end if
end if
if Scene.s_Primitive[intersectedprimitive].lightflag then
matcol = Scene.s_Primitive[intersectedprimitive].Material.diffuse
end if
if MatCol.r>1 then MatCol.r = 1 : if MatCol.r<0 then MatCol.r = 0
if MatCol.g>1 then MatCol.g = 1 : if MatCol.g<0 then MatCol.g = 0
if MatCol.b>1 then MatCol.b = 1 : if MatCol.b<0 then MatCol.b = 0
return type(MatCol.r, MatCol.G,MatCol.b)
else
return type(.05,.05,.05)
end if
End Function
'' main loop
Dim as MaterialT sphereMat, PlaneMat
PlaneMat.Diffuse = type(1,1,1)
PlaneMat.Reflection = .4
SphereMat.Diffuse = type(1,.1,.1)
SphereMat.Reflection = .3
SphereMat.Specular = type(1,1,1)
SphereMat.Highlight = 60
Scene.Add_Light(-15,7,-5,type(.8,.8,.8))
Scene.Add_Light(15,5,20,type(.7,.7,.7))
Scene.Add_Sphere(0,-6.5,15,3,SphereMat)
Scene.Add_Sphere(-4,-6.5,10,3,SphereMat)
Scene.Add_Sphere(4,-6.5,10,3,SphereMat)
Scene.Add_Sphere(0,0,15,3,SphereMat)
Scene.Add_Sphere(-4,0,10,3,SphereMat)
Scene.Add_Sphere(4,0,10,3,SphereMat)
Scene.Add_Sphere(0,7,15,3,SphereMat)
Scene.Add_Sphere(-4,7,10,3,SphereMat)
Scene.Add_Sphere(4,7,10,3,SphereMat)
Scene.Add_Sphere(0,14,15,3,SphereMat)
Scene.Add_Sphere(-4,14,10,3,SphereMat)
Scene.Add_Sphere(4,14,10,3,SphereMat)
Scene.Add_Plane(0,1,0,-10,PlaneMat)
Screenres 640,480,32,2
Dim as colorT finCol
Dim as Ray MainRay
For j as integer = 0 to 479
For i as integer = 0 to 639
MainRay.O = type( 0, 0, -10 )
MainRay.d = type( i-320, 480-j-240,350)
Normalize(MainRay.d)
finCol = Raytrace(MainRay)
Pset(i,j),rgb(finCol.r*255,finCol.g*255,finCol.b*255)
Next
Next
sleep
vector.bi :
''
'' 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
Operator *(L as Single, R as Vector) as Vector
return type( L*R.x, L*R.y, L*R.z )
End operator
Operator -(V as Vector) as Vector
return type(-V.x,-V.y,-V.z)
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
Function GetReflectionVector(InVec as Vector, Normal as Vector) as Vector
return Invec - 2*dot(Normal,InVec) * Normal
End Function
While I may not be able to help with the code, tho i will take a look see if i spot something, I must say that image you posted even with the faults looks very nice :)
I always liked raytracing, the amiga took hours to render even a simple scene but was always amazing to see the end result.
That screenie looks amazing, congrats on your efforts Hezad dude :)
Will try the code out in a bit :D
Wow that renders that scene really fast, its half draw by the time the window comes into view. Really impressive stuff and in such few lines of code :D
Looking really good Hezad. :)
Lookin' great :) Any thoughts about going realtime at some point? ;) There are some great threads sitting round here for that if you're ever curious...Voltage and I and some others talked quite a bit about it, and if I'm not mistaken it was also freebasic :)
Thanks a lot everyone for your answers :)
Ferris > Yep I saw Real time raytracing was more and more discussed and worked on forums(like here :p) /scientific papers, etc.. For now, my objective is to render nice images, I don't have a realtime objective (Also, I'd like to implement different global illumination algorithms in the future => definitively not for realtime purposes ;D)
It looks lovely Hezad, thanks for posting the screen shot, I agree with Ferris too, freebasic can do this in realtime ;)
@Hezad:
Wow, screenshot looks amazing! Any chance of an exe? :)
I think Hezad runs linux, so I have compiled the exe and attach'd it.
@Hezad:
Very nice work! K++ for source
@TinDragon:
Cool! Thanks a lot! K++
Thanks a lot :) and thanks TinDragon for the exe ;)
Shockie > Yep, I guess it could run in real time too at this stage, but there will be -hopefully- more and more possibilities like Global Illumination, so it won't be in real-time in the future anyway :)
Go AO! GO AO! :D
Quote from: Ferris on August 21, 2009
Go AO! GO AO! :D
uh ?
Some (little) news : Added antialiasing. I'm still looking for why there are two phong highlights for one light on each sphere ... (I lost a lot of hair right now :P). Also, there is a problem with the plane intersection function.. I guess I could work on the plane problem but I'm totally stuck on the phong ... Anyway, a new image and the "almost" new code :) (vector.bi hasn't changed)
''
'' Raytracer
''
#include "vector.bi"
Const PRECISION = .1
Const MAX_PRIMITIVES = 200
Const MAX_LIGHTS = 10
Const PRIM_SPHERE = 1
Const PRIM_PLANE = 2
Const MAX_REFLECTIONS = 5
Const CALC_SHADOWS = 0
Type ColorT
as single r,g,b
End Type
Type MaterialT
as ColorT Diffuse, Specular
as single Reflection, Highlight
as single Refraction, RefractionIndex
End type
Type Ray
as vector O,d
as single x,y,z
Declare Sub Update(t as single)
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(t as single)
this.x = this.O.x + this.d.x*t
this.y = this.O.y + this.d.y*t
this.z = this.O.z + this.d.z*t
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,ByRef returnT as single) as integer
End type
Function Primitive.GetIntersection(CRay as Ray,ByRef returnT as single) as integer
Select case This.TypeFlag
Case PRIM_SPHERE
dim as single a = dot(Cray.d, Cray.d)
dim as single b = 2 * dot((Cray.o - type<vector>(this.x,this.y,this.z)),Cray.d )
dim as single c = dot((Cray.o - type<vector>(this.x,this.y,this.z)), (Cray.o - type<vector>(this.x,this.y,this.z))) - (this.r * this.r)
dim as single disc = b * b - 4 * a * c
if disc < PRECISION then return 0
dim as single distSqrt = sqr(disc)
dim as single q
if b < PRECISION then
q = (-b - distSqrt)*.5
else
q = (-b + distSqrt)*.5
end if
dim as single t0 = q / a
dim as single t1 = c / q
if t0>t1 then swap t0,t1
if t1 < PRECISION then return 0
if t0 < PRECISION then
returnT = t1
return 1
else
returnT = t0
return 1
end if
Case PRIM_PLANE
dim as single tempT, num, denum
num = (this.A*CRay.O.x + this.B*CRay.O.y + this.C*CRay.O.z + D)
denum = (this.A*CRay.d.x + this.B*CRay.d.y + this.C*CRay.d.z)
TempT = num/denum
if TempT<PRECISION then
return 0
else
returnT = TempT
return 1
End if
End Select
End Function
Function Primitive.GetNormal(CRay as Ray) as Vector
dim 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
Dim shared as SceneT Scene
Function RayTrace(ByVal R as Ray,ByVal CurReflection as integer = 0) as ColorT
Dim as Ray MainRay
Dim as integer IntersectedPrimitive
dim as single calcT=10000000, oldCalcT=10000000
MainRay = R
intersectedprimitive = -1
For k as integer = 0 to Scene.nb_primitives-1
oldCalcT=calcT
if Scene.s_primitive[k].GetIntersection(MainRay, calcT) then
if oldCalcT>CalcT then
MainRay.Update(calcT)
IntersectedPrimitive = k
end if
End If
next
'' calc color !
if intersectedprimitive <> -1 then
dim as ColorT MatCol = type(0,0,0)
'' Diffuse, specular and shadows
for k as integer = 0 to scene.nb_lights - 1
dim as Vector N, L, V, R
dim as single dotSpec, dotDiff
L = type<vector>(Scene.s_light[k].x,Scene.s_light[k].y,Scene.s_light[k].z) - Type<vector>(MainRay.x,MainRay.y,MainRay.z)
Normalize(L)
N = Scene.s_primitive[intersectedprimitive].GetNormal(MainRay)
V = MainRay.d
R = GetReflectionVector(V,N)
dotDiff = dot(N,L)
dotSpec = dot(L,R)^Scene.s_primitive[intersectedprimitive].Material.Highlight
'' Calculating Shadow
dim as single shade = 1
if CALC_SHADOWS then
dim as single shadowT
dim as Ray ShadowRay
ShadowRay.O = type<vector>(MainRay.x,MainRay.y,MainRay.z) + L*PRECISION
ShadowRay.d = L
for f as integer = 0 to Scene.nb_primitives-1
if Scene.s_primitive[f].GetIntersection(ShadowRay, ShadowT) then
shade = .1 : exit for
End If
next
end if
'' Final Color shading
if dotDiff > 0 then
MatCol.r += dotDiff * Scene.s_primitive[intersectedprimitive].Material.Diffuse.r * Scene.s_light[k].l_color.r * shade
MatCol.g += dotDiff * Scene.s_primitive[intersectedprimitive].Material.Diffuse.g * Scene.s_light[k].l_color.g * shade
MatCol.b += dotDiff * Scene.s_primitive[intersectedprimitive].Material.Diffuse.b * Scene.s_light[k].l_color.b * shade
end if
if dotSpec > 0 then
MatCol.r += dotSpec * Scene.s_primitive[intersectedprimitive].Material.Specular.r * Scene.s_light[k].l_color.r * shade
MatCol.g += dotSpec * Scene.s_primitive[intersectedprimitive].Material.Specular.g * Scene.s_light[k].l_color.g * shade
MatCol.b += dotSpec * Scene.s_primitive[intersectedprimitive].Material.Specular.b * Scene.s_light[k].l_color.b * shade
end if
next
'' Calc reflections
if Scene.s_Primitive[intersectedprimitive].Material.reflection > 0 then
If CurReflection < MAX_REFLECTIONS then
Dim as ColorT refCol
Dim as Ray ReflectionRay
Dim as vector refNormal
refNormal = Scene.s_Primitive[intersectedprimitive].GetNormal(MainRay)
ReflectionRay.O = type <vector> (MainRay.x,MainRay.y,MainRay.z)
ReflectionRay.d = GetReflectionVector(MainRay.d,refNormal)
Normalize(ReflectionRay.d)
'' !!! Recursion !!!
refcol = Raytrace(ReflectionRay,CurReflection+1)
'' !!! --------- !!!
MatCol.r += Scene.s_Primitive[intersectedprimitive].Material.reflection*refcol.r
MatCol.g += Scene.s_Primitive[intersectedprimitive].Material.reflection*refcol.g
MatCol.b += Scene.s_Primitive[intersectedprimitive].Material.reflection*refcol.b
end if
end if
if MatCol.r>1 then MatCol.r = 1 : if MatCol.r<0 then MatCol.r = 0
if MatCol.g>1 then MatCol.g = 1 : if MatCol.g<0 then MatCol.g = 0
if MatCol.b>1 then MatCol.b = 1 : if MatCol.b<0 then MatCol.b = 0
return type(MatCol.r, MatCol.G,MatCol.b)
else
return type(.05,.05,.05)
end if
End Function
'' main loop
Dim as MaterialT sphereMat, PlaneMat
PlaneMat.Diffuse = type(.8,.8,.8)
PlaneMat.Reflection = .5
SphereMat.Diffuse = type(1,.1,.1)
SphereMat.Reflection = .5
SphereMat.Specular = type(1,1,1)
SphereMat.Highlight = 100
Scene.Add_Light(-10,0,0,type(.6,.6,.6))
'Scene.Add_Light(10,0,15,type(.5,.5,.5))
for i as integer = -2 to 2
for j as integer = -2 to 2
SphereMat.Diffuse = type(abs(i)*.5,abs(j)*.5,abs(i*j)*.25)
Scene.Add_Sphere(i*5,j*5,10,2.4,Spheremat)
next
next
'Scene.Add_Plane(0,1,0,-10,PlaneMat)
Screenres 640,480,32,2
Dim as colorT finCol(4)
Dim as Ray MainRay
For j as integer = 0 to 479
For i as integer = 0 to 639
MainRay.O = type( 0, 0, -10 )
MainRay.d = type( i-320, 480-j-240,350)
Normalize(MainRay.d)
finCol(1) = Raytrace(MainRay)
MainRay.O = type( 0, 0, -10 )
MainRay.d = type( i+.5-320, 480-j-240,350)
Normalize(MainRay.d)
finCol(2) = Raytrace(MainRay)
MainRay.O = type( 0, 0, -10 )
MainRay.d = type( i-320, 480-j+.5-240,350)
Normalize(MainRay.d)
finCol(3) = Raytrace(MainRay)
MainRay.O = type( 0, 0, -10 )
MainRay.d = type( i+.5-320, 480-j+.5-240,350)
Normalize(MainRay.d)
finCol(4) = Raytrace(MainRay)
finCol(0).r = (finCol(1).r+finCol(2).r+finCol(3).r+finCol(4).r) * .25
finCol(0).g = (finCol(1).g+finCol(2).g+finCol(3).g+finCol(4).g) * .25
finCol(0).b = (finCol(1).b+finCol(2).b+finCol(3).b+finCol(4).b) * .25
Pset(i,j),rgb(finCol(0).r*255,finCol(0).g*255,finCol(0).b*255)
Next
Next
sleep
Looks delicious. As for the highlights problem, I dont know man, it looks lovely to me.
Thanks shockie :)
The highlight problem has just been resolved (thanks to ROMAECURSORES from freebasic forums). here is a little screen to see the difference (with shadows) ;) I can work on the plane intersection now ;D
That looks great, I look forward to seeing your progress this is one of those things that always impress me, raytracing is such an interesting subject :)
:updance:
In your Plane Intersection you need to be more careful when the 'denom' part of the calculation is 0 (division by 0) or very near to 0 (numeric overflow). Better to ensure the intersection actually happens before working out the intersection point.
Jim
Looks fantastic :D
Jim > Yep I forgot this case ! Thanks a lot for pointing this :) 'just updated the code. Anyway, the glitch is stil here. Just for information, I will post 2 screens to show the bug (on the first screen, there is a plane at x=-5 and on the second screen, a plane at y=10, whatever is the sense of the normal. the last screen is the normal scene with only one plane at y=-5)
Ferris > Thanks ! :D
@Hezad:
New screenshots are amazing! Hoewever i have possible some nice / interesting links for you:
http://fuzzyphoton.tripod.com/howtowrt.htm (http://fuzzyphoton.tripod.com/howtowrt.htm)
Esp following link seems to be very usefull - its from 2004 and shows how to code realtime raytracer... exe and source available...
http://homepages.paradise.net.nz/nickamy/raytracer/raytracer.htm (http://homepages.paradise.net.nz/nickamy/raytracer/raytracer.htm)
Very very interresting links, thanks Vain !
Erm.. Okay, I need help (again..)
I spent days to search where the glitch come from ... I have a problem with my plane intersection routine (or plane normal maybe ? I don't know..).
The point is some planes are ok but some others are rendered very weirdly : It looks like the raytracer doesn't find the closest point on SOME PART of thoses planes (and not all the plane ..) The first image posted is the one with the "ok-planes". The second one is with a plane added on the right side of the image (I don't show you when I put a plane behind the objects .. it's awful).
Here is the "plane part" of the GetNormal and GetIntersection functions :
GetNormal :
normal = -sgn(dot(type<vector>(this.A,this.B,this.C),CRay.d))*type<vector>(this.A,this.B,this.C)
return normal
(the sgn(...) is to ensure the normal faces the ray direction, without it, it's worse)
GetIntersection :
dim as single tempT, num, denum
num = -(A*CRay.O.x+B*CRay.O.y+C*CRay.O.z)+D
denum = (A*CRay.d.x + B*CRay.d.y + C*CRay.d.z)
if ((denum<.0001) and (denum>-.0001)) then return 0
if ((num<.0001) and (num>-.0001)) then return 0
TempT = num/denum
if TempT < 0 then
return 0
else
returnT = TempT
return 1
End if
I tried a LOT of different ways to get the plane intersection (algebric, geometric, Vectorial eq..) but the glitch is always *almost* the same. Bis repetitam about GetNormal().
I also looked in the " Closest Point in the Closest Primitive finding " part of the tracer but I don't see where it could bug. Anyway, here is that part :
dim as single calcT=100000000, oldCalcT
intersectedprimitive = -1
For k as integer = 0 to Scene.nb_primitives-1
oldCalcT=calcT
if Scene.s_primitive[k].GetIntersection(MainRay, calcT) then
if CalcT<=oldCalcT then
MainRay.Update(calcT)
IntersectedPrimitive = k
end if
End If
next
If someone gets the problem here, he will avoid me to pull out more hair and will have my eternal gratitude ;)
Attached :
1) no bug screen
2) buggy screen
3) the source used for the screenshots
if ((num<.0001) and (num>-.0001)) then return 0
I don't understand what this is for.
if (denum == 0) then plane is parallel to the ray and there's no intersecion
if (denum < 0) then the plane faces away from the ray
if (num/denum < 0) then the intersection is behind the origin
Check that both your normal and your ray are unit vectors.
Jim
Thanks for your answer Jim :)
if ((num<.0001) and (num>-.0001)) then return 0
I don't understand what this is for.
if (denum == 0) then plane is parallel to the ray and there's no intersecion
if (denum < 0) then the plane faces away from the ray
if (num/denum < 0) then the intersection is behind the origin
Well because I thought num would never equal 0 but would approach it a lot. So I compare between very small values instead of comparing with 0. But maybe it's useless :P
Check that both your normal and your ray are unit vectors.
Checked several times, but checked again and yep, they are unit vectors :S
Working on refraction at the same time :)
Image looks fantastic to me, but I am a sucker for these simple raytraced scene's of sphere's :)
I look forward to seeing how your progressing with this, are you going to add some form of texture mapping in ?
@Hezad:
Still following your progress and i must say, screens are really cool!
Does the links helped you a bit, to optimize calculation/rendering? ^^
Quote
Quote
if ((num<.0001) and (num>-.0001)) then return 0
I don't understand what this is for.
Well because I thought num would never equal 0 but would approach it a lot. So I compare between very small values instead of comparing with 0. But maybe it's useless
I think num will be 0 when the eye lies on the plane. It's not going to make the calc unstable, unlike when denum is at or near 0.
Good progress on the reflections :)
Jim
Screenshot / Progress are looking fabulous. Very good work, Hezad!
That image would make a great desktop background.
TinDragon > Thanks :D Yep texture mapping is planned (bumpmapping too :)). I'd like to work on procedural textures too, but I want to fix the plane problem before all that ;)
Va!n > Thanks ! The links didn't help yet, I haven't red everything, but i'm sure the source code will be useful when I'll seriously start the optimisation part ;)
Jim > You're right, I suppressed that comparison. Thanks :)
Benny, shockie > Thanks ! ;D
I for one would love to see that image rendered with the spheres closer to the camera and in 1024*768 resolution so I can have it on my desktop, especially with a red/blue and silver colour scheme :)
Here it is ;D
Thanks mate :)
+++++Karma Booooost+++++
Thanks to you :) 'glad you liked it ^^
and now, an very very very very AWESOME new (at least for me :p) :
The "planes bug" IS SOLVED !!! oh gosh, i'm so glad :updance: :updance: I spent the last week to verify my code and the bug was really .. stupid (my object sorting method was wrong).
There are still some things with the planes normal and the refraction calculus to verify but that would be a less motivation-collapsing task ;D A little screen (not really cute, but hey, the planes ARE WELL SORTED !!!)
Anyway, I guess you will understand with this post that I'M GLAD ! I'll post the updated source once the refraction and the the normals are okay :)
Looks wicked Hezad :)
Well done!
Thanks :) Here is a buggy screen of some new wip features.
- Texture mapping ('still looking for the way to properly get UV coordinates on a triangle, as you can see on the screen :S)
- Triangles intersection
- bumpmapping (this one is funny :P)
Looks stunning mate.
The balls almost look bump mapped too.
QuoteLooks stunning mate.
Thanks ;D
QuoteThe balls almost look bump mapped too.
well.. They are xD
Very shiny. :clap:
The bump mapping on the spheres looks really good.
What else are you going to add to this ray tracer?
Looks very cool, well done Hezad :)
Raytraced reflections usually look very synthetic because in reality there are rarely perfect mirrors.
If you're having a closer look, all surface mirror to a tiny percentage. Due to the surface's roughness, rays reflected in different directions resulting in a blurry appearance of reflected objects - the further an object is away the blurrier it appears.
Here (http://www.foro3d.com/tutoriales/Rhinoceros/Material-vray-para-RhinoE/Material-vray-para-RhinoMaterial_Vray_for_Rhino_7.jpg) is a wooden floor for example.
Voltage > Thanks :D Well I'd like it to be able to load some 3D models basically (that's why i'm implementing triangles). In fact I'd like to have a perfectly working basic raytracer to experiment global illumination next.,
TinDragon > Thanks ! :)
hellfire > Yep diffuse reflections are planned ;) I'm just working on bugs before implementing new stuff. Thanks for the image, it's a very attractive one :P
thanks for your kind words everyone :)
For your uv calculation, do a Google search for Barycentric Coordinates.
Jim
Jim > Yep I'm already using barycentric coordinates to intersect the triangle :) 'just don't really know how to retrieve (u,v) texels from (a,b,c) weights.
hellfire > well you tempted me xD Here is a screen of triangles(walls) and diffuse reflection in action ;D
Delicious :)
Just imagine that without coder colours!
Wow, that was very rapid prototyping :)
The reflected environment looks a bit motion-blurred (like it's moving rapidly), might be due to the spherical distortion or maybe the offset of your reflection-rays prefers a certain direction?
shockie > Thanks ;D
Quotecoder colours!
xD !
hellfire >
thanks :) well for the offset, i'm using (the_reflection_ray_itself * a_very_little_number) but I agree, it looks like a cinematic blur .. I'll try to use the normal or the "basic" reflection ray for the offset
Hey :) I'm working on an obj loader but the loaded objects are ... wrong lol The point is I don't know if the problem is in the obj file loader or in the triangle intersection part ... I checked a lot of stuff but nothing to do, I don't find the flaw !
Attached screen : The green stuff is supposed to be a dodecahedron ><
here is the obj loading part :
Function GetWord(stri as string, nb as integer) as string
dim as integer nbchr = len(stri), curspc=0
dim as string retstr=""
for i as integer = 1 to nbchr
if mid(stri,i,1) = " " or i=nbchr then
curspc += 1
if curspc = nb then return retstr
retstr = ""
else
retstr += mid(stri,i,1)
end if
next
return "ERROR"
End function
Sub SceneT.Load_OBJ(byval filen as string,byval Mat as MaterialT, P0 as vector = type(0,0,0), scale as vector = type(1,1,1) )
dim as integer ff = freefile, nbV=0,nbtriangles
dim as string linestr
dim as vector vertexlist(MAX_VERTICE)
Open filen for input as #ff
do
Line input #ff, linestr
select case left(linestr,1)
case "v"
'' add vertex
nbV += 1
vertexlist(nbV).x = val(GetWord(linestr,2))*scale.x + P0.x
vertexlist(nbV).y = val(GetWord(linestr,3))*scale.y + P0.y
vertexlist(nbV).z = val(GetWord(linestr,4))*scale.z + P0.z
case "f"
'' add triangles
this.Add_Triangle(vertexlist(val(GetWord(linestr,2))),vertexlist(val(GetWord(linestr,3))),vertexlist(val(GetWord(linestr,4))),Mat)
end select
Loop until eof(ff)
Close #ff
end sub
and the triangle intersection part :
dim as vector u, v, n, I
dim as Vector d, w0, w
dim as single r, a, b
u = This.p2 - this.p1
v = this.p3 - this.p1
n = u * v
if n.x=0 and n.y=0 and n.z=0 then return 0
d = CRay.d
w0 = CRay.O - this.p1
a = -dot(n,w0)
b = dot(n,d)
if (abs(b) < .00001) then return 0
r = a / b
if (r < 0) then return 0
I = CRay.O + r * d
dim as single uu, uv, vv, wu, wv, Det
uu = dot(u,u)
uv = dot(u,v)
vv = dot(v,v)
w = I - this.p1
wu = dot(w,u)
wv = dot(w,v)
Det = uv * uv - uu * vv
dim as single s, t, _D
_D = 1/Det
s = (uv * wv - vv * wu) * _D
if (s < 0.0 or s > 1.0) then return 0
t = (uv * wu - uu * wv) * _D
if (t < 0.0 or (s + t) > 1.0) then return 0
returnT = r
return 1
Okay, there's some code here, and I know it's not easy to get what's going on in a someone else's code .. But if anyone already had this kind of problem, or have any idea, don't hestitate ;D
nb : oh ! 'forgot to post the screenshot uhuh. thanks to clyde for pointing this out :)
Sorry to interrupt, but all the screenshots are a bit out of place.
Is that just a problem for me?
(WinXP, Firefox 3.5.2)
(http://www.abload.de/thumb/screenshotscty3.png) (http://www.abload.de/image.php?img=screenshotscty3.png)
Back on topic:
"f" can specify polygons with an arbitrary number of vertices.
Are you sure your .obj-file contains only triangles?
I think the loader isn't right. Try a simpler object, such as, say, a triangle, and use Print or a debugger to check the numbers coming out of GetWord.
Jim
QuoteSorry to interrupt, but all the screenshots are a bit out of place.
Is that just a problem for me?
(WinXP, Firefox 3.5.2)
Nobody else has said anything, I am running XP and FF 3.52 and don't get this problem.. I know that there are some problems with this theme that need fixing.
Is this the same for you in all topics?
QuoteIs this the same for you in all topics?
It appears to work fine in other threads (eg here (http://www.dbfinteractive.com/forum/index.php/topic,802.0.html)).
Looks the same in Chrome.
I have had some of the pictures out of place but it seems to only happen on some posts, but not others. I am on vista with FF 3.52, i considered it probably just a glitch as now for example the thread looks fine
Thanks for your answers :)
Concerning the screenshot default, I had the same bug on someone else's thread but I don't remember which :S
Quote"f" can specify polygons with an arbitrary number of vertices.
Are you sure your .obj-file contains only triangles?
Yep, I checked all my obj files, they only use triangles and use only the stuff I'm loading (vertices/faces information)
QuoteI think the loader isn't right. Try a simpler object, such as, say, a triangle, and use Print or a debugger to check the numbers coming out of GetWord.
I checked the GetWord function in a standalone code and it worked very well (I tried stuff like
print GetWord("v 1 0.34534 34034",2) and it returned "1" well)
But, I didn't even thought about editing my own obj file with only one or two triangles >< *me stupid* I'll try that !
Thanks everyone for your answers, I'll try to edit a simpler object file to test it :)
Okay, my researches drive me here :
This obj file is rendered OK :
v -3 0 0
v -2 0 0
v -1 1 0
f 1 2 3
but this one cuts the right side of the triangle :
v -1 0 0
v 1 0 0
v 0 1 0
f 1 2 3
In fact, it seems like it bugs when some coordinates are the opposite sign of some others (eg : x1 = -1,x2=0, x3=1) while it works if all coordinates are the same sign ...
But the bug shouldn't be in the triangle intersection since the background wall is rendered correctly (it has some x coords = -4 and some others = 4)
hum.. right now I really don't understand :S
BTW, there was actually a bug in the GetWord() function but resolving it didn't changed the behavior of the loader ...
Hezad dude, if ever your over at www.pouet.net check out Heaven 7 By Exceed. All software generated.