Перейти к содержимому
Krutoy

Vec3 - код для работы с 3д векторами

Рекомендуемые сообщения

235-3D-vector.png

 

Практически для каждой программы на черепашках или роботах требуется класс 3d вектора. Раньше я пользовался классом vector из СС, но решил расширить функционал. Взяв за основу готовый код для 2д вектора, я написал свой.

 

Кроме стандартных функций +, -, / и * так же реализовано:

  • Быстрые арифметические операции между векторами и скалярами
  • Повороты вокруг осей
  • Проверка на входные параметры
  • Полезные функции в роде unpack()

 

Код вектора:

 

 

 

-- ********************************************************************************** --

-- **   3D Vector                                                                  ** --

-- **                                                                              ** --

-- **   Modified version of 2d vector from                                         ** --

-- **   https://github.com/vrld/hump/blob/master/vector.lua                        ** --

-- **                                                                              ** --
-- **   By Krutoy242                                                               ** --

-- **                                                                              ** --

-- ********************************************************************************** --

 

local assert = assert

local sqrt, cos, sin, atan2 = math.sqrt, math.cos, math.sin, math.atan2

 

local vector = {}

vector.__index = vector

 

local function new(x,y,z)

  return setmetatable({x = x or 0, y = y or 0, z = z or 0}, vector)

end

local zero = new(0,0,0)

 

local function isvector(v)

  return type(v) == 'table' and type(v.x) == 'number' and type(v.y) == 'number' and type(v.z) == 'number'

end

 

function vector:clone()

  return new(self.x, self.y, self.z)

end

 

function vector:unpack()

  return self.x, self.y, self.z

end

 

function vector:__tostring()

  return "("..tonumber(self.x)..","..tonumber(self.y)..","..tonumber(self.z)..")"

end

 

function vector.__unm(a)

  return new(-a.x, -a.y, -a.z)

end

 

function vector.__add(a,b)

  assert(isvector(a) and isvector(b), "Add: wrong argument types (<vector> expected)")

  return new(a.x+b.x, a.y+b.y, a.z+b.z)

end

 

function vector.__sub(a,b)

  assert(isvector(a) and isvector(b), "Sub: wrong argument types (<vector> expected)")

  return new(a.x-b.x, a.y-b.y, a.z-b.z)

end

 

function vector.__mul(a,b)

  if type(a) == "number" then

    return new(a*b.x, a*b.y, a*b.z)

  elseif type(b) == "number" then

    return new(b*a.x, b*a.y, b*a.z)

  else

    assert(isvector(a) and isvector(b), "Mul: wrong argument types (<vector> or <number> expected)")

    return a.x*b.x + a.y*b.y + a.z*b.z

  end

end

 

function vector.__div(a,b)

  assert(isvector(a) and type(b) == "number", "wrong argument types (expected <vector> / <number>)")

  return new(a.x / b, a.y / b, a.z / b)

end

 

function vector.__eq(a,b)

  return a.x == b.x and a.y == b.y and a.z == b.z

end

 

function vector.__lt(a,b)

  return a.x < b.x and a.y < b.y and a.z < b.z

end

 

function vector.__le(a,b)

  return a.x <= b.x and a.y <= b.y and a.z <= b.z

end

 

function vector.permul(a,b)

  assert(isvector(a) and isvector(b), "permul: wrong argument types (<vector> expected)")

  return new(a.x*b.x, a.y*b.y, a.z*b.z)

end

 

function vector:len2()

  return self.x * self.x + self.y * self.y + self.z * self.z

end

 

function vector:len()

  return sqrt(self.x * self.x + self.y * self.y + self.z * self.z)

end

 

function vector.dist(a, b)

  assert(isvector(a) and isvector(b), "dist: wrong argument types (<vector> expected)")

  local dx = a.x - b.x

  local dy = a.y - b.y

  local dz = a.z - b.z

  return sqrt(dx * dx + dy * dy + dz * dz)

end

 

function vector.dist2(a, b)

  assert(isvector(a) and isvector(b), "dist: wrong argument types (<vector> expected)")

  local dx = a.x - b.x

  local dy = a.y - b.y

  local dz = a.z - b.z

  return (dx * dx + dy * dy + dz * dz)

end

 

function vector:normalize_inplace()

  local l = self:len()

  if l > 0 then

    self.x, self.y, self.z = self.x / l, self.y / l, self.z / l

  end

  return self

end

 

function vector:normalized()

  return self:clone():normalize_inplace()

end

 

function vector:rotate_inplace_z(phi)

  local c, s = cos(phi), sin(phi)

  self.x, self.y = c * self.x - s * self.y, s * self.x + c * self.y

  return self

end

function vector:rotate_inplace_x(phi)

  local c, s = cos(phi), sin(phi)

  self.y, self.z = c * self.y - s * self.z, s * self.y + c * self.z

  return self

end

function vector:rotate_inplace_y(phi)

  local c, s = cos(phi), sin(phi)

  self.z, self.x = c * self.z - s * self.x, s * self.z + c * self.x

  return self

end

 

function vector:rotated_z(phi)

  local c, s = cos(phi), sin(phi)

  return new(c * self.x - s * self.y, s * self.x + c * self.y, self.z)

end

function vector:rotated_x(phi)

  local c, s = cos(phi), sin(phi)

  return new(self.x, c * self.y - s * self.z, s * self.y + c * self.z)

end

function vector:rotated_y(phi)

  local c, s = cos(phi), sin(phi)

  return new(s * self.z + c * self.x, self.y, c * self.z - s * self.x)

end

 

function vector:cross(v)

  assert(isvector(v), "cross: wrong argument types (<vector> expected)")

  return new(self.Y * v.Z - self.Z * v.Y,

             self.Z * v.X - self.X * v.Z,

             self.X * v.Y - self.Y * v.X)

end

 

function vector:trim_inplace(maxLen)

  local s = maxLen * maxLen / self:len2()

  s = (s > 1 and 1) or math.sqrt(s)

  self.x, self.y, self.z = self.x * s, self.y * s, self.z * s

  return self

end

 

function vector:trimmed(maxLen)

  return self:clone():trim_inplace(maxLen)

end

 

 

-- the module

return setmetatable({new = new, isvector = isvector, zero = zero},

{__call = function(_, ...) return new(...) end})

 

 

 

 

Для подключения в свой код используйте функцию require (для ОС), или оберните в функцию как это сделано здесь:

http://pastebin.com/2t1rqjek

 

 

Пример использования:

local a = vec3(1,2,3)

local b = a*10
local c = b:rotated_z(math.pi) + a
local x,y,z = b:unpack()
print( c )

 

 

Пишите если пригодился, или если нашли ошибку.

Изменено пользователем Krutoy

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

И куда его к черепашке прилепить?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

И куда его к черепашке прилепить?

 

По механике движения, эта библиотека будет полезнее для дронов.

 

А вообще векторные рассчеты - очень полезная библиотека. Взять хотя бы GPS, которым программисты CC пользуются "искаропки".

Он весь построен на векторах.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Эх, пишу пушку динамитную, начал свой велосипед городить и тут бац! Ладно, сейчас поковыряем...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Эх, пишу пушку динамитную, начал свой велосипед городить и тут бац! Ладно, сейчас поковыряем...

Велосипедостроение - это неизлечимая болезнь.  ;)

Мы потеряли много хороших парней на велосипедах...

Изменено пользователем Krutoy

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Велосипедостроение - это неизлечимая болезнь.  ;)

Мы потеряли много хороших парней на велосипедах...

Да я же начал писать до того, как ты выложил библиотеку.

И потом, как мне ещё, школьнику, проверить свои знания в тригонометрии? (А у меня ничего не вышло).

 

И да, вот такой код:

local vec3=require("vec3")
local a = vec3(3,1,1)
print(a)
local c = a:rotated_z(math.pi)
print(c)
local a = vec3(3,0,0)
print(a)
local c = a:rotated_z(math.pi)
print(c)

Выведет следующее:

(3,1,1)

(-3,-1,1)

(3,0,0)

(-3,3.6739403974421e-16,0)

 

Это надо исправить

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Выведет следующее:

(3,1,1)

(-3,-1,1)

(3,0,0)

(-3,3.6739403974421e-16,0)

 

Это надо исправить

 

А в этом виноват не мой код а сам интерпритатор луа. Пруф.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Велосипедостроение - это неизлечимая болезнь.  ;)

Мы потеряли много хороших парней на велосипедах...

Велосипед помогает развивать мускулатуру, и не даёт накаливанию жира, в этом случай можно интерпретировать - это к мозгу, а не телу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Велосипедостроение - это неизлечимая болезнь.  ;)

Мы потеряли много хороших парней на велосипедах...

А сколько потеряли на изобретании колеса...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А сколько потеряли на изобретании колеса...

 Не для всех колесо полезно. https://youtu.be/j2mGjiz4vIw  :wacko:

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в тему...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


×
×
  • Создать...