Should pull these apart and study them separately

This commit is contained in:
Smaug123
2023-05-07 00:26:47 +01:00
parent fe31792cdd
commit 2d3acc188b
2 changed files with 36 additions and 22 deletions

View File

@@ -15,13 +15,14 @@ type InfinitePlaneStyle =
[<RequireQualifiedAccess>]
module InfinitePlane =
let pureOutgoing (strikePoint : Point) (normal : UnitVector) (incomingRay : Ray) : Ray =
let plane = Plane.makeOrthonormalSpannedBy (Ray.make strikePoint normal) incomingRay
let pureOutgoing (strikePoint : Point) (normal : UnitVector) (incomingRay : byref<Ray>) : unit =
let plane = Plane.makeOrthonormalSpannedBy' strikePoint normal incomingRay
match plane with
| ValueNone ->
// Incoming ray is directly along the normal
Ray.flip incomingRay |> Ray.parallelTo strikePoint
Ray.flipInPlace incomingRay
Ray.translateToIntersect strikePoint incomingRay
| ValueSome plane ->
// Incoming ray is (plane1.ray) plane1 + (plane2.ray) plane2
// We want the reflection in the normal, so need (plane1.ray) plane1 - (plane2.ray) plane2
@@ -29,14 +30,20 @@ module InfinitePlane =
let tangentComponent = (UnitVector.dot plane.V2 (Ray.vector incomingRay))
let s =
// (plane.Point + plane.V1 * normalComponent) + plane.V2 * tangentComponent
tangentComponent
|> Ray.walkAlongRay (Ray.walkAlongRay plane.Point plane.V1 normalComponent) plane.V2
let newVector =
Point.differenceToThenFrom s strikePoint
|> Ray.make' strikePoint
|> Vector.unitise
// This is definitely safe. It's actually a logic error if this fails.
|> ValueOption.get
incomingRay.Origin <- strikePoint
incomingRay.Vector <- newVector
let newColour (incomingColour : Pixel) albedo colour =
Pixel.combine incomingColour colour |> Pixel.darken albedo
@@ -57,21 +64,24 @@ module InfinitePlane =
| InfinitePlaneStyle.FuzzedReflection (albedo, colour, fuzz, rand) ->
let newColour = newColour incomingRay.Colour albedo colour
let pureOutgoing = pureOutgoing strikePoint normal incomingRay.Ray
let mutable outgoing = Unchecked.defaultof<_>
pureOutgoing strikePoint normal &incomingRay.Ray
// Henceforth `incomingRay` is actually the outgoing ray: we mutated it above.
let mutable isDone = false
while obj.ReferenceEquals (outgoing, null) do
while not isDone do
let offset = UnitVector.random rand (Point.dimension pointOnPlane)
let sphereCentre = Ray.walkAlong pureOutgoing 1.0
let sphereCentre = Ray.walkAlong incomingRay.Ray 1.0
let target = Ray.walkAlongRay sphereCentre offset (fuzz / 1.0<fuzz>)
let output = Point.differenceToThenFrom target strikePoint |> Ray.make' strikePoint
let outgoing = Point.differenceToThenFrom target strikePoint
match output with
match Vector.unitise outgoing with
| ValueNone -> ()
| ValueSome output -> outgoing <- output
| ValueSome output ->
incomingRay.Ray.Vector <- output
Ray.translateToIntersect strikePoint incomingRay.Ray
isDone <- true
incomingRay.Colour <- newColour
incomingRay.Ray <- outgoing
ValueNone
@@ -93,8 +103,9 @@ module InfinitePlane =
ValueNone
| InfinitePlaneStyle.PureReflection (albedo, colour) ->
incomingRay.Colour <- newColour incomingRay.Colour albedo colour
incomingRay.Ray <- pureOutgoing strikePoint normal incomingRay.Ray
let newColour = newColour incomingRay.Colour albedo colour
incomingRay.Colour <- newColour
pureOutgoing strikePoint normal &incomingRay.Ray
ValueNone

View File

@@ -61,23 +61,26 @@ module Plane =
Point = Ray.origin r1
}
let makeOrthonormalSpannedBy (r1 : Ray) (r2 : Ray) : OrthonormalPlane ValueOption =
let coefficient = UnitVector.dot r1.Vector r2.Vector
let makeOrthonormalSpannedBy' (r1Origin : Point) (r1Vector : UnitVector) (r2 : Ray) : OrthonormalPlane ValueOption =
let coefficient = UnitVector.dot r1Vector r2.Vector
let vec2 =
UnitVector.difference' r2.Vector (UnitVector.scale coefficient r1.Vector)
UnitVector.difference' r2.Vector (UnitVector.scale coefficient r1Vector)
|> Vector.unitise
match vec2 with
| ValueNone -> ValueNone
| ValueSome v2 ->
{
V1 = r1.Vector
V1 = r1Vector
V2 = v2
Point = Ray.origin r1
Point = r1Origin
}
|> ValueSome
let inline makeOrthonormalSpannedBy (r : Ray) (r2 : Ray) =
makeOrthonormalSpannedBy' r.Origin r.Vector r2
/// 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 |> ValueOption.get