godot-nim/godot/core/vector3.nim
2018-06-04 11:50:37 +07:00

242 lines
No EOL
5.8 KiB
Nim

# Copyright (c) 2018 Xored Software, Inc.
import math, hashes
import godotbase, godotcoretypes
{.push stackTrace: off.}
proc vec3*(): Vector3 {.inline.} =
Vector3()
proc vec3*(x, y, z: float32): Vector3 {.inline.} =
Vector3(x: x, y: y, z: z)
proc `$`*(self: Vector3): string {.inline.} =
result = newStringOfCap(40)
result.add('(')
result.add($self.x)
result.add(", ")
result.add($self.y)
result.add(", ")
result.add($self.z)
result.add(')')
proc hash*(self: Vector3): Hash {.inline, noinit.} =
!$(self.x.hash() !& self.y.hash() !& self.z.hash())
proc `+`*(a, b: Vector3): Vector3 {.inline.} =
result.x = a.x + b.x
result.y = a.y + b.y
result.z = a.z + b.z
proc `+=`*(a: var Vector3, b: Vector3) {.inline.} =
a.x += b.x
a.y += b.y
a.z += b.z
proc `-`*(a, b: Vector3): Vector3 {.inline.} =
result.x = a.x - b.x
result.y = a.y - b.y
result.z = a.z - b.z
proc `-=`*(a: var Vector3, b: Vector3) {.inline.} =
a.x -= b.x
a.y -= b.y
a.z -= b.z
proc `*`*(a, b: Vector3): Vector3 {.inline.} =
result.x = a.x * b.x
result.y = a.y * b.y
result.z = a.z * b.z
proc `*=`*(a: var Vector3, b: Vector3) {.inline.}=
a.x *= b.x
a.y *= b.y
a.z *= b.z
proc `*`*(a: Vector3; b: float32): Vector3 {.inline.} =
result.x = a.x * b
result.y = a.y * b
result.z = a.z * b
proc `*`*(b: float32; a: Vector3): Vector3 {.inline.} =
a * b
proc `*=`*(a: var Vector3; b: float32) {.inline.} =
a.x *= b
a.y *= b
a.z *= b
proc `/`*(a, b: Vector3): Vector3 =
result.x = a.x / b.x
result.y = a.y / b.y
result.z = a.z / b.z
proc `/=`*(a: var Vector3; b: Vector3) {.inline.} =
a.x /= b.x
a.y /= b.y
a.z /= b.z
proc `/`*(a: Vector3; b: float32): Vector3 =
result.x = a.x / b
result.y = a.y / b
result.z = a.z / b
proc `/=`*(a: var Vector3; b: float32) {.inline.} =
a.x /= b
a.y /= b
a.z /= b
proc `==`*(a, b: Vector3): bool {.inline.} =
a.x == b.x and a.y == b.y and a.z == b.z
proc `<`*(a, b: Vector3): bool =
if a.x == b.x:
if a.y == b.y:
return a.z < b.z
return a.y < b.y
return a.x < b.x
proc `-`*(self: Vector3): Vector3 =
result.x = -self.x
result.y = -self.y
result.z = -self.z
proc `[]`*(self: Vector3, idx: range[0..2]): float32 {.inline.} =
cast[array[3, float32]](self)[idx]
proc `[]`*(self: var Vector3, idx: range[0..2]): var float32 {.inline.} =
cast[ptr array[3, float32]](addr self)[][idx]
proc `[]=`*(self: var Vector3, idx: range[0..2],
val: float32) {.inline.} =
case idx:
of 0: self.x = val
of 1: self.y = val
of 2: self.z = val
proc minAxis*(self: Vector3): int {.inline.} =
if self.x < self.y:
if self.x < self.z: 0 else: 2
else:
if self.y < self.z: 1 else: 2
proc maxAxis*(self: Vector3): int {.inline.} =
if self.x < self.y:
if self.y < self.z: 2 else: 1
else:
if self.x < self.z: 2 else: 0
proc length*(self: Vector3): float32 {.inline.} =
let x2 = self.x * self.x
let y2 = self.y * self.y
let z2 = self.z * self.z
result = sqrt(x2 + y2 + z2)
proc lengthSquared*(self: Vector3): float32 {.inline.} =
let x2 = self.x * self.x
let y2 = self.y * self.y
let z2 = self.z * self.z
result = x2 + y2 + z2
proc normalize*(self: var Vector3) {.inline.} =
let len = self.length()
if len == 0:
self.x = 0
self.y = 0
self.z = 0
else:
self.x /= len
self.y /= len
self.z /= len
proc normalized*(self: Vector3): Vector3 {.inline.} =
result = self
result.normalize()
proc isNormalized*(self: Vector3): bool {.inline.} =
self.lengthSquared().isEqualApprox(1.0'f32)
proc zero*(self: var Vector3) {.inline.} =
self.x = 0
self.y = 0
self.z = 0
proc inverse*(self: Vector3): Vector3 {.inline.} =
vec3(1.0'f32 / self.x, 1.0'f32 / self.y, 1.0'f32 / self.z)
proc cross*(self, other: Vector3): Vector3 {.inline.} =
vec3(
self.y * other.z - self.z * other.y,
self.z * other.x - self.x * other.z,
self.x * other.y - self.y * other.x)
proc dot*(self, other: Vector3): float32 {.inline.} =
self.x * other.x + self.y * other.y + self.z * other.z
proc abs*(self: Vector3): Vector3 {.inline.} =
vec3(abs(self.x), abs(self.y), abs(self.z))
proc sign*(self: Vector3): Vector3 {.inline.} =
vec3(sign(self.x), sign(self.y), sign(self.z))
proc floor*(self: Vector3): Vector3 {.inline.} =
vec3(floor(self.x), floor(self.y), floor(self.z))
proc ceil*(self: Vector3): Vector3 {.inline.} =
vec3(ceil(self.x), ceil(self.y), ceil(self.z))
proc lerp*(self: Vector3, other: Vector3, t: float32): Vector3 {.inline.} =
vec3(
self.x + t * (other.x - self.x),
self.y + t * (other.y - self.y),
self.z + t * (other.z - self.z)
)
proc distanceTo*(self, other: Vector3): float32 {.inline.} =
(other - self).length()
proc distanceSquaredTo*(self, other: Vector3): float32 {.inline.} =
(other - self).lengthSquared()
proc angleTo*(self, other: Vector3): float32 {.inline.} =
arctan2(self.cross(other).length(), self.dot(other))
proc slide*(self, n: Vector3): Vector3 {.inline.} =
assert(n.isNormalized())
result = self - n * self.dot(n)
proc reflect*(self, n: Vector3): Vector3 {.inline.} =
assert(n.isNormalized())
result = 2.0'f32 * n * self.dot(n) - self
proc bounce*(self, n: Vector3): Vector3 {.inline.} =
-self.reflect(n)
proc snap*(self: var Vector3, other: Vector3) =
self.x = stepify(self.x, other.x)
self.y = stepify(self.y, other.y)
self.z = stepify(self.z, other.z)
proc snapped*(self: Vector3, other: Vector3): Vector3 =
result = self
result.snap(other)
proc cubicInterpolate*(self, b, preA, postB: Vector3;
t: float32): Vector3 =
let p0 = preA
let p1 = self
let p2 = b
let p3 = postB
let t2 = t * t
let t3 = t2 * t
result = 0.5 * ((p1 * 2.0) +
(-p0 + p2) * t +
(2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 +
(-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3)
{.pop.} # stackTrace: off