From VisualWorks® NonCommercial, 7.4.1 of May 30, 2006 on September 20, 2007 at 7:53:34 pm
Ray
Smalltalk
Core.Object
false
none
orig dir
RayBench
(none)
RayBench
Smalltalk
Core.Object
false
none
RayBench
(none)
Hit
Smalltalk
Core.Object
false
none
lambda normal
RayBench
(none)
Sphere
Smalltalk
Core.Object
false
none
center radius
RayBench
(none)
Group
Smalltalk
Core.Object
false
none
bound objs
RayBench
(none)
Vec
Smalltalk
Core.Object
false
none
x y z
RayBench
(none)
Ray class instance creation
orig: o dir: d
^self new setOrig: o dir: d; yourself
Ray accessing
dir
^dir
orig
^orig
Ray private
setOrig: o dir: d
orig := o.
dir := d
RayBench class example
pixelSize: px level: level
"Time millisecondsToRun: [self pixelSize: 64 level: 4]"
| scene out lf pxStr ss |
ss := 4.
scene := self createLevel: level center: #(0d -1d 1d) asVec radius: 1d.
out := 'image.pgm' asFilename writeStream.
lf := String with: Character lf. pxStr := px printString.
out nextPutAll: ('P5', lf, pxStr, ' ', pxStr, lf, '255', lf); binary.
px - 1 to: 0 by: -1 do: [:y | 0 to: px - 1 do: [:x |
| gain |
gain := 0d.
0 to: ss - 1 do: [:dx | 0 to: ss - 1 do: [:dy |
| eye dir |
dir := Vec x: x + (dx asDouble / ss) - (px / 2) y: y + (dy asDouble / ss) - (px / 2) z: px.
eye := Ray orig: #(0d 0d -4d) asVec dir: dir unitise.
gain := gain + (self rayTraceLight: #(-1d -3d 2d) asVec unitise ray: eye scene: scene)]].
out nextPut: (255 * gain / (ss * ss)) rounded]].
out close
RayBench class private
createLevel: level center: position radius: radius
| sphere group factor |
sphere := Sphere center: position radius: radius.
level = 1 ifTrue: [^sphere].
group := Group bound: (Sphere center: position radius: 3d * radius).
group objs add: sphere.
factor := 3d * radius / 12 sqrt.
#(-1 1) do: [:dx | #(-1 1) do: [:dz |
| childPos |
childPos := position + ((Vec x: dx y: 1 z: dz) * factor).
group objs add: (self createLevel: level - 1 center: childPos radius: radius / 2d)]].
^group
rayTraceLight: light ray: camRay scene: scene
| hit refPos spGai spRay spHit delta infinity zeroVec |
delta := 2.22045e-16 sqrt.
infinity := 1d308.
zeroVec := Vec x: 0d y: 0d z: 0d.
hit := scene intersectHit: (Hit lambda: infinity normal: zeroVec) ray: camRay.
hit lambda = infinity ifTrue: [^0].
refPos := camRay orig + (camRay dir * hit lambda) + (hit normal * delta).
spGai := light dot: hit normal.
spGai >= 0 ifTrue: [^0].
spRay := Ray orig: refPos dir: (light * -1).
spHit := scene intersectHit: (Hit lambda: infinity normal: zeroVec) ray: spRay.
^spHit lambda = infinity ifTrue: [spGai negated] ifFalse: [0]
Core.Array converting
asVec
^Vec newFrom: self
Hit class instance creation
lambda: l normal: n
^self new setLambda: l normal: n; yourself
Hit accessing
lambda
^lambda
normal
^normal
Hit private
setLambda: l normal: n
lambda := l.
normal := n
Sphere class instance creation
center: c radius: r
^self new setCenter: c radius: r; yourself
Sphere accessing
center
^center
radius
^radius
Sphere processing
intersectHit: hit ray: ray
| len vec |
len := self raySphere: ray.
len >= hit lambda ifTrue: [^hit].
vec := ray orig + (ray dir * len - center).
^Hit lambda: len normal: vec unitise
raySphere: ray
| vec b det sqDet t2 t1 |
vec := center - ray orig.
b := vec dot: ray dir.
det := b * b - (vec dot: vec) + (radius * radius).
det < 0 ifTrue: [^1d308].
sqDet := det sqrt.
t2 := b + sqDet.
t2 < 0 ifTrue: [^1d308].
t1 := b - sqDet.
^t1 > 0 ifTrue: [t1] ifFalse: [t2]
Sphere private
setCenter: c radius: r
center := c.
radius := r
Group class instance creation
bound: aSphere
^self new initialize; setBound: aSphere; yourself
Group private
setBound: aSphere
bound := aSphere
Group accessing
objs
^objs
Group processing
intersectHit: hit ray: ray
| len |
len := bound raySphere: ray.
len >= hit lambda ifTrue: [^hit].
^objs inject: hit into: [:h :ss | ss intersectHit: h ray: ray]
Group initialize-release
initialize
objs := OrderedCollection new
release
objs := nil.
super release
Vec class instance creation
newFrom: array
^self x: (array at: 1) y: (array at: 2) z: (array at: 3)
x: x y: y z: z
^self new setX: x y: y z: z; yourself
Vec arithmetic
* scale
^self class x: (x * scale) y: (y * scale) z: (z * scale)
+ other
^self class x: (x + other x) y: (y + other y) z: (z + other z)
- other
^self class x: (x - other x) y: (y - other y) z: (z - other z)
dot: other
^(x * other x) + (y * other y) + (z * other z)
unitise
^self * (1 / (self dot: self) sqrt)
Vec private
setX: newX y: newY z: newZ
x := newX.
y := newY.
z := newZ
Vec accessing
x
^x
y
^y
z
^z