1
0

Added transformation operations

This commit is contained in:
neviyn 2020-11-08 21:45:23 +00:00
parent 1d87ef2303
commit 1c2887e809

129
src/transformations.nim Normal file
View File

@ -0,0 +1,129 @@
import "./tuple"
import "./matrix"
import math
proc translation*(x, y, z: float): Matrix = matrix(@[1.0, 0.0, 0.0, x, 0.0, 1.0, 0.0, y, 0.0, 0.0, 1.0, z, 0.0, 0.0, 0.0, 1.0], 4, 4)
proc scaling*(x, y, z: float): Matrix = matrix(@[x, 0.0, 0.0, 0.0, 0.0, y, 0.0, 0.0, 0.0, 0.0, z, 0.0, 0.0, 0.0, 0.0, 1.0], 4, 4)
proc rotationX*(radians: float): Matrix = matrix(@[1.0, 0.0, 0.0, 0.0, 0.0, cos(radians), -sin(radians), 0.0, 0.0, sin(radians), cos(radians), 0.0, 0.0, 0.0, 0.0, 1.0], 4, 4)
proc rotationY*(radians: float): Matrix = matrix(@[cos(radians), 0.0, sin(radians), 0.0, 0.0, 1.0, 0.0, 0.0, -sin(radians), 0.0, cos(radians), 0.0, 0.0, 0.0, 0.0, 1.0], 4, 4)
proc rotationZ*(radians: float): Matrix = matrix(@[cos(radians), -sin(radians), 0.0, 0.0, sin(radians), cos(radians), 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0], 4, 4)
proc shearing*(x_y, x_z, y_x, y_z, z_x, z_y: float): Matrix = matrix(@[1.0, x_y, x_z, 0.0, y_x, 1.0, y_z, 0.0, z_x, z_y, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0], 4, 4)
when isMainModule:
import unittest
suite "transformations":
test "Multiplying by a translation matrix":
let transform = translation(5.0, -3.0, 2.0)
let p = point(-3.0, 4.0, 5.0)
check(transform * p == point(2.0, 1.0, 7.0))
test "Multiplying by the inverse of a translation matrix":
let transform = translation(5.0, -3.0, 2.0).inverse()
let p = point(-3.0, 4.0, 5.0)
check(transform * p == point(-8.0, 7.0, 3.0))
test "Translation does not affect vectors":
let transform = translation(5.0, -3.0, 2.0)
let v = vector(-3.0, 4.0, 5.0)
check(transform * v == v)
test "Scaling matrix applied to a point":
let transform = scaling(2.0, 3.0, 4.0)
let p = point(-4.0, 6.0, 8.0)
check(transform * p == point(-8.0, 18.0, 32.0))
test "Scaling matrix applied to a vector":
let transform = scaling(2.0, 3.0, 4.0)
let v = vector(-4.0, 6.0, 8.0)
check(transform * v == vector(-8.0, 18.0, 32.0))
test "Multiplying by the inverse of a scaling matrix":
let transform = scaling(2.0, 3.0, 4.0).inverse()
let v = vector(-4.0, 6.0, 8.0)
check(transform * v == vector(-2.0, 2.0, 2.0))
test "Reflection is scaling by a negative value":
let transform = scaling(-1.0, 1.0, 1.0)
let p = point(2.0, 3.0, 4.0)
check(transform * p == point(-2.0, 3.0, 4.0))
test "Rotation around the X axis":
let p = point(0.0, 1.0, 0.0)
let halfQuarter = rotationX(PI / 4)
let fullQuarter = rotationX(PI / 2)
check(halfQuarter * p == point(0.0, sqrt(2.0)/2.0, sqrt(2.0)/2.0))
check(fullQuarter * p == point(0.0, 0.0, 1.0))
test "Inverse of a rotation rotates in the opposite direction":
let p = point(0.0, 1.0, 0.0)
let halfQuarter = rotationX(PI / 4).inverse()
check(halfQuarter * p == point(0.0, sqrt(2.0)/2.0, -sqrt(2.0)/2.0))
test "Rotation around the Y axis":
let p = point(0.0, 0.0, 1.0)
let halfQuarter = rotationY(PI / 4)
let fullQuarter = rotationY(PI / 2)
check(halfQuarter * p == point(sqrt(2.0)/2.0, 0.0, sqrt(2.0)/2.0))
check(fullQuarter * p == point(1.0, 0.0, 0.0))
test "Rotation around the Z axis":
let p = point(0.0, 1.0, 0.0)
let halfQuarter = rotationZ(PI / 4)
let fullQuarter = rotationZ(PI / 2)
check(halfQuarter * p == point(-sqrt(2.0)/2.0, sqrt(2.0)/2.0, 0.0))
check(fullQuarter * p == point(-1.0, 0.0, 0.0))
test "Shearing transformation moves X in proportion to Y":
let t = shearing(1.0, 0.0, 0.0, 0.0, 0.0, 0.0)
let p = point(2.0, 3.0, 4.0)
check(t * p == point(5.0, 3.0, 4.0))
test "Shearing transformation moves X in proportion to Z":
let t = shearing(0.0, 1.0, 0.0, 0.0, 0.0, 0.0)
let p = point(2.0, 3.0, 4.0)
check(t * p == point(6.0, 3.0, 4.0))
test "Shearing transformation moves Y in proportion to X":
let t = shearing(0.0, 0.0, 1.0, 0.0, 0.0, 0.0)
let p = point(2.0, 3.0, 4.0)
check(t * p == point(2.0, 5.0, 4.0))
test "Shearing transformation moves Y in proportion to Z":
let t = shearing(0.0, 0.0, 0.0, 1.0, 0.0, 0.0)
let p = point(2.0, 3.0, 4.0)
check(t * p == point(2.0, 7.0, 4.0))
test "Shearing transformation moves Z in proportion to X":
let t = shearing(0.0, 0.0, 0.0, 0.0, 1.0, 0.0)
let p = point(2.0, 3.0, 4.0)
check(t * p == point(2.0, 3.0, 6.0))
test "Shearing transformation moves Z in proportion to Y":
let t = shearing(0.0, 0.0, 0.0, 0.0, 0.0, 1.0)
let p = point(2.0, 3.0, 4.0)
check(t * p == point(2.0, 3.0, 7.0))
test "Individual transformations applied in sequence":
let p = point(1.0, 0.0, 1.0)
let r = rotationX(PI / 2)
let s = scaling(5.0, 5.0, 5.0)
let t = translation(10.0, 5.0, 7.0)
let p2 = r * p
check(p2 == point(1.0, -1.0, 0.0))
let p3 = s * p2
check(p3 == point(5.0, -5.0, 0.0))
let p4 = t * p3
check(p4 == point(15.0, 0.0, 7.0))
test "Chained transformations are applied in reverse order":
let p = point(1.0, 0.0, 1.0)
let r = rotationX(PI / 2)
let s = scaling(5.0, 5.0, 5.0)
let t = translation(10.0, 5.0, 7.0)
let combo = t * s * r
check(combo * p == point(15.0, 0.0, 7.0))