Moveable camera

This commit is contained in:
Patrick Stevens
2021-04-11 14:45:04 +01:00
parent 136eecc6f2
commit 1fe0847a1e
5 changed files with 57 additions and 25 deletions

View File

@@ -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 =

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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

View File

@@ -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 =