mirror of
https://github.com/Smaug123/ray-tracing-fsharp
synced 2025-10-05 20:08:43 +00:00
Moveable camera
This commit is contained in:
@@ -48,7 +48,7 @@ module SampleImages =
|
||||
let aspectRatio = 16.0 / 9.0
|
||||
let origin = Point.make 0.0 0.0 0.0
|
||||
let camera =
|
||||
Camera.makeBasic 2.0 aspectRatio origin (Vector.make 0.0 0.0 1.0 |> Vector.unitise |> Option.get)
|
||||
Camera.makeBasic 2.0 aspectRatio origin (Vector.make 0.0 0.0 1.0 |> Vector.unitise |> Option.get) (Vector.make 0.0 1.0 0.0)
|
||||
let pixels = 400
|
||||
{
|
||||
Objects =
|
||||
@@ -64,7 +64,7 @@ module SampleImages =
|
||||
let aspectRatio = 16.0 / 9.0
|
||||
let origin = Point.make 0.0 0.0 0.0
|
||||
let camera =
|
||||
Camera.makeBasic 2.0 aspectRatio origin (Vector.make 0.0 0.0 1.0 |> Vector.unitise |> Option.get)
|
||||
Camera.makeBasic 2.0 aspectRatio origin (Vector.make 0.0 0.0 1.0 |> Vector.unitise |> Option.get) (Vector.make 0.0 1.0 0.0)
|
||||
let pixels = 400
|
||||
{
|
||||
Objects =
|
||||
@@ -82,7 +82,7 @@ module SampleImages =
|
||||
let aspectRatio = 16.0 / 9.0
|
||||
let origin = Point.make 0.0 0.0 0.0
|
||||
let camera =
|
||||
Camera.makeBasic 7.0 aspectRatio origin (Vector.make 0.0 0.0 1.0 |> Vector.unitise |> Option.get)
|
||||
Camera.makeBasic 7.0 aspectRatio origin (Vector.make 0.0 0.0 1.0 |> Vector.unitise |> Option.get) (Vector.make 0.0 1.0 0.0)
|
||||
let pixels = 200
|
||||
{
|
||||
Objects =
|
||||
@@ -115,7 +115,7 @@ module SampleImages =
|
||||
let aspectRatio = 16.0 / 9.0
|
||||
let origin = Point.make 0.0 0.0 0.0
|
||||
let camera =
|
||||
Camera.makeBasic 7.0 aspectRatio origin (Vector.make 0.0 0.0 1.0 |> Vector.unitise |> Option.get)
|
||||
Camera.makeBasic 7.0 aspectRatio origin (Vector.make 0.0 0.0 1.0 |> Vector.unitise |> Option.get) (Vector.make 0.0 1.0 0.0)
|
||||
let pixels = 1200
|
||||
{
|
||||
Objects =
|
||||
@@ -141,7 +141,7 @@ module SampleImages =
|
||||
let aspectRatio = 16.0 / 9.0
|
||||
let origin = Point.make 0.0 0.0 0.0
|
||||
let camera =
|
||||
Camera.makeBasic 1.0 aspectRatio origin (Vector.make 0.0 0.0 1.0 |> Vector.unitise |> Option.get)
|
||||
Camera.makeBasic 1.0 aspectRatio origin (Vector.make 0.0 0.0 1.0 |> Vector.unitise |> Option.get) (Vector.make 0.0 1.0 0.0)
|
||||
let pixels = 300
|
||||
{
|
||||
Objects =
|
||||
@@ -168,7 +168,7 @@ module SampleImages =
|
||||
let aspectRatio = 16.0 / 9.0
|
||||
let origin = Point.make -2.0 2.0 -1.0
|
||||
let camera =
|
||||
Camera.makeBasic 1.0 aspectRatio origin (Point.differenceToThenFrom (Point.make 0.0 0.0 1.0) origin |> Vector.unitise |> Option.get)
|
||||
Camera.makeBasic 1.0 aspectRatio origin (Point.differenceToThenFrom (Point.make 0.0 0.0 1.0) origin |> Vector.unitise |> Option.get) (Vector.make 0.0 1.0 0.0)
|
||||
let pixels = 200
|
||||
{
|
||||
Objects =
|
||||
|
@@ -11,10 +11,13 @@ module TestPlane =
|
||||
let ``Orthogonalise does make orthogonal vectors`` () =
|
||||
let property (p : Plane) : bool =
|
||||
let orth = Plane.orthonormalise p |> Option.get
|
||||
let v1, v2 = Plane.basis orth
|
||||
Float.equal (UnitVector.dot (Ray.vector v1) (Ray.vector v2)) 0.0
|
||||
&& Float.equal (UnitVector.dot (Ray.vector v1) (Ray.vector v1)) 1.0
|
||||
&& Float.equal (UnitVector.dot (Ray.vector v2) (Ray.vector v2)) 1.0
|
||||
let v1, v2 = Plane.basis (Vector.make 0.0 1.0 0.0) orth
|
||||
let dotVectors = UnitVector.dot (Ray.vector v1) (Ray.vector v2)
|
||||
let v1Length = UnitVector.dot (Ray.vector v1) (Ray.vector v1)
|
||||
let v2Length = UnitVector.dot (Ray.vector v2) (Ray.vector v2)
|
||||
Float.equal dotVectors 0.0
|
||||
&& Float.equal v1Length 1.0
|
||||
&& Float.equal v2Length 1.0
|
||||
|
||||
property
|
||||
|> Prop.forAll (Arb.fromGen TestUtils.planeGen)
|
||||
|
@@ -27,32 +27,29 @@ type Camera =
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Camera =
|
||||
|
||||
/// View angle is in radians (specified arbitrarily)
|
||||
let makeBasic
|
||||
(focalLength : float)
|
||||
(aspectRatio : float)
|
||||
(origin : Point)
|
||||
(viewDirection : UnitVector)
|
||||
(viewUp : Vector)
|
||||
: Camera
|
||||
=
|
||||
let height = 2.0
|
||||
let basis = UnitVector.basis 3
|
||||
let xAxis =
|
||||
basis.[0]
|
||||
|> Ray.make origin
|
||||
let yAxis =
|
||||
basis.[1]
|
||||
|> Ray.make origin
|
||||
|
||||
let view = Ray.make origin viewDirection
|
||||
let corner = Ray.walkAlong view focalLength
|
||||
|
||||
let viewPlane = Plane.makeNormalTo' corner viewDirection
|
||||
let xAxis, yAxis = Plane.basis viewUp viewPlane
|
||||
|
||||
{
|
||||
FocalLength = focalLength
|
||||
ViewportHeight = height
|
||||
ViewportWidth = aspectRatio * height
|
||||
View = view
|
||||
ViewportXAxis =
|
||||
Ray.parallelTo (Ray.walkAlong view focalLength) xAxis
|
||||
ViewportYAxis =
|
||||
Ray.parallelTo (Ray.walkAlong view focalLength) yAxis
|
||||
ViewportXAxis = xAxis
|
||||
ViewportYAxis = yAxis
|
||||
SamplesPerPixel = 50
|
||||
}
|
@@ -19,6 +19,29 @@ type OrthonormalPlane =
|
||||
[<RequireQualifiedAccess>]
|
||||
module Plane =
|
||||
|
||||
let makeNormalTo (point : Point) (Vector (x, y, z) as v) : OrthonormalPlane =
|
||||
let v1 =
|
||||
if Float.equal z 0.0 then
|
||||
Vector.make 0.0 0.0 1.0
|
||||
else
|
||||
Vector.make 1.0 1.0 ((-x - y) / z)
|
||||
let v2 =
|
||||
Vector.cross v v1
|
||||
|> Vector.unitise
|
||||
|> Option.get
|
||||
let v1 =
|
||||
v1
|
||||
|> Vector.unitise
|
||||
|> Option.get
|
||||
|
||||
{
|
||||
Point = point
|
||||
V1 = v1
|
||||
V2 = v2
|
||||
}
|
||||
|
||||
let inline makeNormalTo' (point : Point) (UnitVector v) = makeNormalTo point v
|
||||
|
||||
let orthonormalise (plane : Plane) : OrthonormalPlane option =
|
||||
let coeff = UnitVector.dot plane.V1 plane.V2
|
||||
let vec2 =
|
||||
@@ -41,6 +64,12 @@ module Plane =
|
||||
Point = Ray.origin r1
|
||||
}
|
||||
|
||||
let basis (plane : OrthonormalPlane) : Ray * Ray =
|
||||
Ray.make plane.Point plane.V1,
|
||||
Ray.make plane.Point plane.V2
|
||||
/// Construct a basis for this plane, whose second ("up") component is `viewUp` when projected onto the plane.
|
||||
let basis (viewUp : Vector) (plane : OrthonormalPlane) : Ray * Ray =
|
||||
let viewUp = Vector.unitise viewUp |> Option.get
|
||||
let v1Component = UnitVector.dot plane.V1 viewUp
|
||||
let v2Component = UnitVector.dot plane.V2 viewUp
|
||||
let v2 = Vector.sum (UnitVector.scale v1Component plane.V1) (UnitVector.scale v2Component plane.V2) |> Vector.unitise |> Option.get
|
||||
let v1 = Vector.sum (UnitVector.scale v2Component plane.V1) (UnitVector.scale (-v1Component) plane.V2) |> Vector.unitise |> Option.get
|
||||
Ray.make plane.Point v1,
|
||||
Ray.make plane.Point v2
|
||||
|
@@ -47,6 +47,9 @@ module Vector =
|
||||
let make (x : float) (y : float) (z : float) =
|
||||
Vector (x, y, z)
|
||||
|
||||
let cross (Vector (x, y, z)) (Vector (a, b, c)) : Vector =
|
||||
make (y * c - z * b) (z * a - x * c) (x * b - a * y)
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module UnitVector =
|
||||
let rec random (floatProducer : FloatProducer) (dimension : int) : UnitVector =
|
||||
|
Reference in New Issue
Block a user