// The Goose standard library: `vec` (docs/stdlib.md): small vectors as // plain structs. Elementwise + - * / are the language's (§6.1); the // scalar * / broadcast too. The functions here combine components. The int aliases are // i32 because vectors are data (§3.1), and an i32 component widens into an // i64 index implicitly. import math; struct vec2 { x: T, y: T } struct vec3 { x: T, y: T, z: T } struct vec4 { x: T, y: T, z: T, w: T } type float2 = vec2; type float3 = vec3; type float4 = vec4; type double2 = vec2; type double3 = vec3; type double4 = vec4; type int2 = vec2; type int3 = vec3; type int4 = vec4; let float2_0 = float2 { 0.0, 0.0 }; let float2_1 = float2 { 1.0, 1.0 }; let float3_0 = float3 { 0.0, 0.0, 0.0 }; let float3_1 = float3 { 1.0, 1.0, 1.0 }; let float4_0 = float4 { 0.0, 0.0, 0.0, 0.0 }; let float4_1 = float4 { 1.0, 1.0, 1.0, 1.0 }; let double2_0 = double2 { 0.0, 0.0 }; let double2_1 = double2 { 1.0, 1.0 }; let double3_0 = double3 { 0.0, 0.0, 0.0 }; let double3_1 = double3 { 1.0, 1.0, 1.0 }; let double4_0 = double4 { 0.0, 0.0, 0.0, 0.0 }; let double4_1 = double4 { 1.0, 1.0, 1.0, 1.0 }; let int2_0 = int2 { 0, 0 }; let int2_1 = int2 { 1, 1 }; let int3_0 = int3 { 0, 0, 0 }; let int3_1 = int3 { 1, 1, 1 }; let int4_0 = int4 { 0, 0, 0, 0 }; let int4_1 = int4 { 1, 1, 1, 1 }; fn dot(a: vec2, b: vec2) -> T { a.x * b.x + a.y * b.y } fn dot(a: vec3, b: vec3) -> T { a.x * b.x + a.y * b.y + a.z * b.z } fn dot(a: vec4, b: vec4) -> T { a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w } fn cross(a: vec3, b: vec3) -> vec3 { vec3 { a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x } } fn length_sq(v: vec2) -> T { dot(v, v) } fn length_sq(v: vec3) -> T { dot(v, v) } fn length_sq(v: vec4) -> T { dot(v, v) } // Float vectors only: sqrt has f32 and f64 forms. fn length(v: vec2) -> T { sqrt(length_sq(v)) } fn length(v: vec3) -> T { sqrt(length_sq(v)) } fn length(v: vec4) -> T { sqrt(length_sq(v)) } fn normalize(v: vec2) -> vec2 { v / length(v) } fn normalize(v: vec3) -> vec3 { v / length(v) } fn normalize(v: vec4) -> vec4 { v / length(v) } fn distance(a: vec2, b: vec2) -> T { length(a - b) } fn distance(a: vec3, b: vec3) -> T { length(a - b) } fn distance(a: vec4, b: vec4) -> T { length(a - b) } fn lerp(a: vec2, b: vec2, t: T) -> vec2 { vec2 { a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t } } fn lerp(a: vec3, b: vec3, t: T) -> vec3 { vec3 { a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t } } fn lerp(a: vec4, b: vec4, t: T) -> vec4 { vec4 { a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t, a.w + (b.w - a.w) * t } } fn xy(v: vec3) -> vec2 { vec2 { v.x, v.y } } fn xy(v: vec4) -> vec2 { vec2 { v.x, v.y } } fn xyz(v: vec4) -> vec3 { vec3 { v.x, v.y, v.z } }