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

Развлечение 3D-графика для очков из OpenPeripheral

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

Думаю, тут самое подходящее место, чтобы опубликовать мое новое творение :)


Узнал я недавно о таком прекрасной модификации для любимой игры: OpenComputers. Разузнав подробности, решил попробовать что-нибудь для нее написать, ведь изучение нового яп всегда пойдет на пользу. И тут меня потянуло на графику. Но стандартные мониторы оставляют желать и искать лучшего. Благо, есть такое дополнение, как OpenPeripheral, расширяющее возможности OC, и, помимо прочего, добавляющее очки, через которые можно нарисовать на экране что-то четкое.

Думаю, не стоит больше растягивать предисловие. Представляю вашему вниманию простенький низкоуровневый(пока) графический интерфейс: я назвал его Glass3D.

 

Что можно с ним сделать?

Добавить в список вершины по x,y,z

Создать полигоны по 3-м вершинам

Преобразовывать группы вершин при помощи матриц

Быстро все отрисовывать благодаря sync-функции из api моста очков(~30 fps может)

 

Зачем?

Отрисовывать красивые схемы, голлограммы из ваших программ, которые смогут быть всегда перед глазами :D

 

Исходники

https://raw.githubusercontent.com/Trientalis/OpenComputersProgramms/master/Glass3D.lua

 

Использование

Описание интерфейсов

addVertex3D(x,y,z,h):index -- создает новую вершину, параметр h пока не используется(вообще нужен для масштаба)

 

addVertices3D({x1,y1,z1,x2,y2,z2...,xn,yn,zn}):{index1,...indexn}  -- принимает координаты точек, возвращает массив индексов

 

removeVertex3D(index)  -- удаляет вершину, побочный эффект: смещение, будет решено в будующих версиях

 

addPolygon3D({index1,index2,index3},{color,opacity=1}):name  -- добавляет полигон по трем точкам и цвету, возвращает имя полигона index1+"_"+index2+"_"+index3

 

removePolygon3D(name)  -- удаляет полигон, без побочных эффектов

 

transform({index1,...,indexn},{number1,...,number16})  -- умножает текущую матрицу вершин на переданную

 

update()  -- применяет матрицы вершин на их координаты, рисует полигоны

 

setFocalLenght(number)  -- задает расстояние от глаз пользователя до экрана

 

 

демо: 

--Тетраэдр, немного кривой, ну да ладно
local gl=dofile("Glass3D.lua")
--gl.setFocalLenght(200)
gl.addPolygon3D({gl.addVertex3D(-20,15,0),gl.addVertex3D(20,15,0),gl.addVertex3D(0,-20,0)},{color=0xff00ff,opacity=1})--Добавляет 3 вершины и полигон из них
gl.addPolygon3D({1,2,gl.addVertex3D(0,0,-25)},{color=0x00ff00,opacity=1})--2вершины у нас уже есть, нужна еще одна
gl.addPolygon3D({2,3,4},{color=0x0000ff,opacity=1})--остальные 2 грани
gl.addPolygon3D({3,1,4},{color=0xff0000,opacity=1})
local angle=-0.1*math.pi/180--угол поворота

for i=1,50 do--вращение по Y
gl.transform({1,2,3,4},{math.cos(angle),0,-math.sin(angle),0,
                        0,1,0,0,
                        math.sin(angle),0,math.cos(angle),0,
                        0,0,0,1})
gl.update()
os.sleep(0.03)
end

for i=1,50 do--вращение по Y+Z
gl.transform({1,2,3,4},{math.cos(angle),math.sin(angle),0,0,-math.sin(angle),math.cos(angle),0,0,0,0,1,0,0,0,0,1})
gl.update()
os.sleep(0.03)
end

for i=1,60 do--вращение по Y+X+Z
gl.transform({1,2,3,4},{1,0,0,0,
                        0,math.cos(angle),math.sin(angle),0,
                        0,-math.sin(angle),math.cos(angle),0,
                        0,0,0,1})
gl.update()
os.sleep(0.03)
end

post-18473-0-35145300-1460031945_thumb.pngpost-18473-0-34780900-1460031955_thumb.pngpost-18473-0-19303300-1460031968_thumb.png

 

О матрицах

матрица параллельного переноса:

  [ 1  0  0  0 ]

  [ 0  1  0  0 ]

  [ 0  0  1  0 ]

  [ x  y  z  1 ]

матрица растяжения/сжатия:

  [ z  0  0  0 ]

  [ 0  y  0  0 ]

  [ 0  0  x  0 ]

  [ 0  0  0  1 ]

матрица поворота вокруг оси x:

  [ 1    0      0    0 ]

  [ 0  cos α  sin α  0 ]

  [ 0 -sin α  cos α  0 ]

  [ 0    0      0    1 ]

матрица поворота вокруг оси y:

  [ cos α  0 -sin α  0 ]

  [  0    1    0    0 ]

  [ sin α  0  cos α  0 ]

  [  0    0    0    1 ]

матрица поворота вокруг оси z:

  [ cos α  sin α  0  0 ]

  [-sin α  cos α  0  0 ]

  [  0      0    1  0 ]

  [  0      0    0  1 ]

 

 

 

Баги, ошибки

Сейчас уже можно нормально пользоваться этим api для простых целей, но имеется один старанный баг, и я никак не могу найти ошибочное место в коде: если применить матрицу поворота по одной оси, потом обновить экран(матрица сольется с вершиной), потом применить поворот по другой оси, эффект прежней матрицы остается :smile14:А, может быть, это вообще не баг, с матрицы я раньше использовал только для одной из осей.

И еще подхрамывает постоянность частота кадров: увеличивается со временем.

 

Спасибо за внимание, надеюсь, вам понравилась моя работа.

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

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


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

Ну, про отступы сейчас тебе Лёша расскажет. Я скажу вот что:

- библиотеку желательно называть строчными буквами, размещать в директории lib и подключать процедурой require.

- обращаться к вершинам по индексу - не слишком удачное решение. Представь, что у тебя не четыре вершины, а сто четыре. На втором десятке ты в них запутаешься. Я бы сделал, чтоб функция addVertex3D возвращала объект-вершину, а не её индекс.

- хотелось бы описание функций библиотеки. Какие параметры принимают, что возвращают.

А так, очень даже не плохо.

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


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

Спасибо за отзыв :)

процедурой require.
 

Это был тестовый код, его удобно использовать, если вносишь изменения в либу

 

- хотелось бы описание функций библиотеки. Какие параметры принимают, что возвращают.

В исходниках, где не понятно, я описал

 

 

Я бы сделал, чтоб функция addVertex3D возвращала объект-вершину, а не её индекс.

Хорошо, так и сделаю в следующей версии

 

Еще забыл указать один важный момент: спасибо, Fingercomp, за инфу про якори

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

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


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

 

 

В исходниках, где не понятно, я описал
Комментарии это, конечно, хорошо. Но, согласись, рыться в чужом исходнике, что б понять, какие параметры нужны функции и какие функции есть вообще, не очень удобно.

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


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

Немного ворчания по поводу тщательно выписанной лицензии.

 

Все что публикуется на Pastebin получает автоматом лицензию cc by-sa 3.0 .

Если планируется публиковать под другой, следует воспользоваться другим сервисом. ;)

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


Ссылка на сообщение
Поделиться на других сайтах
--Тетраэдр, немного кривой, ну да ладно

Аааааа, как? Зачем? Ты убиваешь во мне перфекциониста такими методами.

Когда я тестировал и писал 3D рендеринг, я делал идеальный тетраэдр (моя любимая геометрическая фигура). Но ты меня убил вот этим "немного кривой". Так сложно использовать формулы? Так сложно логически составить формулы для составления точных точек тетраэдра?

Учи тригонометрию.

for i=1,60 do--вращение по Y+X+Z
gl.transform({1,2,3,4},{1,0,0,0,
                        0,math.cos(angle),math.sin(angle),0,
                        0,-math.sin(angle),math.cos(angle),0,
                        0,0,0,1})
gl.update()
os.sleep(0.03)
end 

Правильное применение отступам? Ага, их как раз так и применяют  :smile3:

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

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


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

 

 

Так сложно использовать формулы?

Наизусть не помню, а зач специально искать в сети, это же просто тестовый код

 

Ага, их как раз так и применяют

Не понял. Что не так?

[a,b,c,d,

 e,f,g,h,

 i, j, k, l,

 m,n,o,p]

Матрица 4 на 4, эти отступы увеличивают читаемость кода.


 

 

Все что публикуется на Pastebin получает автоматом лицензию cc by-sa 3.0 .

Спасибо, не знал

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


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

 

 

Наизусть не помню, а зач специально искать в сети, это же просто тестовый код

Да забудь вообще слово "учить". Формулы нужно самому уметь выводить, а не надеяться на интернет, таблицу сложения и прочий мусор выдуманный гуманитариями.

В общем я решил за тебя сделать столь сложный труд, вот 4 координаты точек правильного тетраэдра:

local x=10 -- любое число - длинна грани тетраэдра
{-x/2,0,0}
{x/2,0,0}
{0,0,math.sqrt(3)*x/2}
{0,math.sqrt(x^2-(x/(2*math.sqrt(3)))^2),x/(2*math.sqrt(3))}

Тригонометрия и не такое может.

 

 

 

Не понял. Что не так?

Мне кажется можно было читаемость повысить другим способом. Вынести таблицу в отдельную локальную переменную или например добавить отступы в коде где их нет. А их нигде нет.

 

 

 

local angle=-0.1*math.pi/180--угол поворота

Используешь по старинке math.pi/180 ?

Так уже давно никто не делает. Почитай тут про библиотеку math, там есть такие полезные функции как math.deg и math.rad, они делают то что тебе надо.

 

И да, если часто используешь какую то библиотеку, то желательно написать следующее в начале кода:

local math = math

По идее локальная переменная должна работать быстрее чем глобальная и это должно ускорить код.

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


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

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

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

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

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

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

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

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

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


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