package main import ( "fmt" maths "math" ) type Vec3 struct { X, Y, Z float64 } func (v Vec3) Neg() Vec3 { return Vec3{-v.X, -v.Y, -v.Z}; } func (v Vec3) Add(w Vec3) Vec3 { return Vec3{v.X + w.X, v.Y + w.Y, v.Z + w.Z}; } func (v Vec3) Sub(w Vec3) Vec3 { return Vec3{v.X - w.X, v.Y - w.Y, v.Z - w.Z}; } func (v Vec3) Mul(w Vec3) Vec3 { return Vec3{v.X * w.X, v.Y * w.Y, v.Z * w.Z}; } func (v Vec3) Div(w Vec3) Vec3 { return Vec3{v.X / w.X, v.Y / w.Y, v.Z / w.Z}; } func (v Vec3) MagSqr() float64 { return v.Dot(v); } func (v Vec3) Mag() float64 { return maths.Sqrt(v.MagSqr()); } func (v Vec3) Unit() Vec3 { m := v.Mag(); return Vec3{v.X / m, v.Y / m, v.Z / m}; } func (v Vec3) Dot(w Vec3) float64 { return v.X * w.X + v.Y * w.Y + v.Z * w.Z; } func (v Vec3) Cross(w Vec3) Vec3 { return Vec3{v.Y * w.Z - v.Z * w.Y, v.Z * w.X - v.X * w.Z, v.X * w.Y - v.Y * w.X}; } func (v Vec3) ToPPM() string { i := Interval{0, 0.999}; r := uint8(256 * i.Clamp(v.X)); g := uint8(256 * i.Clamp(v.Y)); b := uint8(256 * i.Clamp(v.Z)); return fmt.Sprintf("%3d %3d %3d", r, g, b); } func Splat(f float64) Vec3 { return Vec3{f, f, f}; }