122 lines
3 KiB
Go
122 lines
3 KiB
Go
package main
|
|
|
|
import (
|
|
"math"
|
|
)
|
|
|
|
type Vector3 struct {
|
|
X, Y, Z float64
|
|
}
|
|
|
|
func (u Vector3) GetColor(p Vector3) Vector3 {
|
|
return u
|
|
}
|
|
|
|
func (u Vector3) Add(v Vector3) Vector3 {
|
|
return Vector3{u.X + v.X, u.Y + v.Y, u.Z + v.Z}
|
|
}
|
|
|
|
func (u Vector3) Neg() Vector3 {
|
|
return Vector3{-u.X, -u.Y, -u.Z}
|
|
}
|
|
|
|
func (u Vector3) Sub(v Vector3) Vector3 {
|
|
return u.Add(v.Neg())
|
|
}
|
|
|
|
func (u Vector3) Scale(a float64) Vector3 {
|
|
return Vector3{a * u.X, a * u.Y, a * u.Z}
|
|
}
|
|
|
|
func (u Vector3) Dot(v Vector3) float64 {
|
|
return u.X*v.X + u.Y*v.Y + u.Z*v.Z
|
|
}
|
|
|
|
func (u Vector3) Cross(v Vector3) Vector3 {
|
|
return Vector3{u.Y*v.Z - u.Z*v.Y, u.Z*v.X - u.X*v.Z, u.X*v.Y - u.Y*v.X}
|
|
}
|
|
|
|
func (u Vector3) LengthSquared() float64 {
|
|
return u.Dot(u)
|
|
}
|
|
|
|
func (u Vector3) Length() float64 {
|
|
return math.Sqrt(u.LengthSquared())
|
|
}
|
|
|
|
func (u Vector3) Normalized() Vector3 {
|
|
return u.Scale(1.0 / u.Length())
|
|
}
|
|
|
|
func (u Vector3) Round() Vector3 {
|
|
round := math.Round
|
|
return Vector3{round(u.X), round(u.Y), round(u.Z)}
|
|
}
|
|
|
|
func (u Vector3) Abs() Vector3 {
|
|
abs := math.Abs
|
|
return Vector3{abs(u.X), abs(u.Y), abs(u.Z)}
|
|
}
|
|
|
|
func (u Vector3) Max(x float64) Vector3 {
|
|
return Vector3{max(u.X, x), max(u.Y, x), max(u.Z, x)}
|
|
}
|
|
|
|
func (u Vector3) Min(x float64) Vector3 {
|
|
return Vector3{min(u.X, x), min(u.Y, x), min(u.Z, x)}
|
|
}
|
|
|
|
// i incident, n normal. Both vector should be normalized
|
|
func Reflect(i Vector3, n Vector3) Vector3 {
|
|
y := i.Dot(n)
|
|
return i.Add(n.Scale(2 * y))
|
|
}
|
|
|
|
// Todo : Refract
|
|
|
|
// Rodrigues' rotation formula. rotVector should be normalized
|
|
func Rotate(u Vector3, rotVector Vector3, angle float64) Vector3 {
|
|
cos, sin := math.Cos(angle), math.Sin(angle)
|
|
vec1 := u.Scale(cos)
|
|
vec2 := rotVector.Cross(u).Scale(sin)
|
|
vec3 := rotVector.Scale(rotVector.Dot(u) * (1 - cos))
|
|
return vec1.Add(vec2).Add(vec3)
|
|
}
|
|
|
|
func Mix(u Vector3, v Vector3, k float64) Vector3 {
|
|
l := (1 - k)
|
|
return Vector3{u.X*l + v.X*k, u.Y*l + v.Y*k, u.Z*l + v.Z*k}
|
|
}
|
|
|
|
func (v Vector3) Unpack() (float64, float64, float64) {
|
|
return v.X, v.Y, v.Z
|
|
}
|
|
|
|
// Return position, and units vectors of spherical into cartesian coords (r, theta, phi) units vecs
|
|
func (v Vector3) SphericalToCartesian() (Vector3, Vector3, Vector3, Vector3) {
|
|
p, theta, phi := v.Unpack()
|
|
cos_theta, sin_theta := math.Cos(theta), math.Sin(theta)
|
|
cos_phi, sin_phi := math.Cos(phi), math.Sin(phi)
|
|
|
|
cart_pos := Vector3{p * cos_theta * cos_phi, p * sin_theta * sin_phi, p * cos_theta}
|
|
unit_vec_r := Vector3{sin_theta * cos_phi, sin_theta * cos_phi, cos_theta}
|
|
unit_vec_theta := Vector3{cos_theta * cos_phi, cos_theta * sin_phi, -sin_theta}
|
|
unit_vec_phi := Vector3{-sin_phi, cos_phi, 0}
|
|
return cart_pos, unit_vec_r, unit_vec_theta, unit_vec_phi
|
|
}
|
|
|
|
// Others maths thingies
|
|
func Clamp(x float64, a float64, b float64) float64 {
|
|
return min(max(x, a), b)
|
|
}
|
|
|
|
func (v Vector3) Clamp(a float64, b float64) Vector3 {
|
|
x, y, z := v.Unpack()
|
|
x, y, z = Clamp(x, a, b), Clamp(y, a, b), Clamp(z, a, b)
|
|
return Vector3{x, y, z}
|
|
}
|
|
|
|
func SmoothStep(x float64, a float64, b float64) float64 {
|
|
x = Clamp((x-a)/(b-a), 0, 1)
|
|
return x * x * (3.0 - 2.0*x)
|
|
}
|