Vec3
Vectores 3D: operaciones, ángulos, interpolación, suavizado y proyecciones.
Vector de tres componentes para posiciones, direcciones, velocidades, giros en grados, escalas y colores.
Las funciones se pueden llamar de dos formas equivalentes: a:distance(b) o Vec3.distance(a, b).
local a = Vec3(1, 2, 3)
local b = Vec3() -- (0, 0, 0)
local c = a + b * 2 - Vec3.up -- suma, resta y escala
local d = a * Vec3(1, 0, 1) -- producto por componentes
print(a.x, a.y, a.z, a) -- los campos se leen y escriben
print("posicion: " .. a) -- se concatena con texto: posicion: (1.000, 2.000, 3.000)
local largo = a:length()
local dir = (b - a):normalized()
local cerca = a:distance(b) < 2
local medio = Vec3.lerp(a, b, 0.5)
Crear y copiar
| Miembro | Descripción |
|---|---|
Vec3(x, y, z), Vec3() | Vector nuevo (sin argumentos: cero). |
Vec3(x, y) | Con z = 0. |
Vec3(v), v:copy() | Copia independiente de otro vector. |
x, y, z | Componentes (lectura y escritura). |
v:set(x, y, z) | Cambia los tres componentes de golpe. |
v:unpack() | Devuelve x, y, z: local x, y, z = v:unpack(). |
Vec3.zero, one, up, down, left, right, forward, back | Constantes. forward es (0, 0, -1): en Cramion "adelante" es -Z. |
Operadores
| Operación | Resultado |
|---|---|
a + b, a - b, -a | Suma, resta y opuesto. |
v * 2, 2 * v, v / 2 | Escala por un número. |
a * b, a / b | Multiplica o divide por componentes. |
a == b | Iguales exactamente (para "casi iguales" usa approximately). |
tostring(v), "texto" .. v | Texto (1.000, 2.000, 3.000). |
Longitud, distancia y ángulos
| Función | Descripción |
|---|---|
v:length(), v:sqrLength() | Longitud y longitud al cuadrado (más rápida para comparar). |
v:normalized() | Mismo sentido, longitud 1 (o cero si v es cero). |
v:clampLength(max) | Lo acorta si es más largo que max (limitar una velocidad). |
Vec3.distance(a, b), Vec3.sqrDistance(a, b) | Distancia entre dos puntos (y al cuadrado). |
Vec3.dot(a, b) | Producto escalar: positivo si miran hacia el mismo lado. |
Vec3.cross(a, b) | Producto vectorial: perpendicular a los dos. |
Vec3.angle(a, b) | Ángulo entre dos direcciones, en grados (0 a 180). |
Vec3.signedAngle(a, b, eje) | Ángulo con signo alrededor de eje (-180 a 180): a qué lado queda b. |
Interpolar y mover
| Función | Descripción |
|---|---|
Vec3.lerp(a, b, t) | Punto entre a y b (t se limita a 0..1). |
Vec3.lerpUnclamped(a, b, t) | Igual, sin limitar t (extrapola). |
Vec3.slerp(a, b, t) | Gira la dirección de a hacia b y mezcla su longitud. |
Vec3.moveTowards(actual, objetivo, paso) | Avanza hacia el objetivo como mucho paso sin pasarse. |
Vec3.smoothDamp(actual, objetivo, vel, tiempo, dt [, maxVel]) | Seguimiento suave, como un muelle sin rebote. Devuelve dos valores: la posición nueva y la velocidad (guárdala para el siguiente frame). |
Proyectar y reflejar
| Función | Descripción |
|---|---|
Vec3.project(v, sobre) | La parte de v en la dirección sobre. |
Vec3.projectOnPlane(v, normal) | Aplasta v sobre un plano: por ejemplo, moverse por una rampa. |
Vec3.reflect(dir, normal) | Rebote de una dirección contra una superficie. |
Por componentes
| Función | Descripción |
|---|---|
Vec3.scale(a, b) | Multiplica componente a componente (como a * b). |
Vec3.min(a, b), Vec3.max(a, b) | El menor o el mayor de cada componente. |
v:abs(), v:floor(), v:ceil(), v:round() | Valor absoluto y redondeos de cada componente (útil para rejillas). |
Vec3.approximately(a, b [, margen]) | Casi iguales (distancia menor que margen, 0.0001 por defecto). |
Ejemplos
Seguir con suavidad (smoothDamp)
local Seguir = { properties = { objetivo = "Jugador", suavidad = 0.25 } }
function Seguir:Start()
self.meta = Scene.find(self.objetivo)
self.vel = Vec3.zero:copy()
end
function Seguir:LateUpdate(dt)
if not self.meta then return end
local destino = self.meta.position + Vec3(0, 3, 6)
local pos
pos, self.vel = Vec3.smoothDamp(self.entity.position, destino, self.vel, self.suavidad, dt)
self.entity.position = pos
end
return Seguir
¿Está delante de mí? ¿A qué lado?
local haciaEl = (enemigo.position - self.entity.position):normalized()
local delante = Vec3.dot(self.entity.forward, haciaEl) > 0.5 -- dentro de un cono de ~60 grados
local lado = Vec3.signedAngle(self.entity.forward, haciaEl, Vec3.up) -- > 0: a la izquierda, < 0: a la derecha
Copias: las propiedades de una entidad devuelven una copia, así que
self.entity.position.y = 3 no la mueve. Lee, modifica y vuelve a asignar:
local p = self.entity.position; p.y = 3; self.entity.position = p.
En cambio, local b = a no copia: las dos variables son el mismo vector (como una tabla). Usa
a:copy() si vas a modificar uno sin tocar el otro, y no modifiques las constantes como Vec3.zero.
¿Algo no queda claro o falta algo? Pregunta en el Discord.