Работа с трёхмерными объектами штатными средствами

Программирование - Практика программирования

16
Рисуем объёмные геометрические фигуры в 1С средствами встроенного языка без внешних компонент

Не так давно я увидел статью, в которой автор рассказывает, как он заполнял коробки товарами. Для меня в ней круто всё, но больше всего привлекла визуализация результата. Мне стало интересно, насколько 1С умеет работать с 3D графикой и это вылилось в ряд статей, в которых я показывал, как постепенно учился работать с двухмерной графикой. Теперь я хочу продемонстрировать, как дошёл до трёхмерной системы координат. Штатными средствами.

На самом деле, вычисление вершин трёхмерных объектов является довольно несложной проблемой. Это всё та же задача со стрелками часов из моего предыдущего поста, только стрелок становится больше. Достаточно знать длины сторон и угол. Я понял это не сразу, и примитивные фигуры рисовал, жёстко прописывая координаты.

НоваяКоордината = ТаблицаКоординат.Добавить();
НоваяКоордината.Х = -50;
НоваяКоордината.У = 50;
НоваяКоордината.З = 0;
	
НоваяКоордината = ТаблицаКоординат.Добавить();
НоваяКоордината.Х = -50;
НоваяКоордината.У = -50;
НоваяКоордината.З = 0;
	
НоваяКоордината = ТаблицаКоординат.Добавить();
НоваяКоордината.Х = 50;
НоваяКоордината.У = 50;
НоваяКоордината.З = 0;
	
НоваяКоордината = ТаблицаКоординат.Добавить();
НоваяКоордината.Х = 50;
НоваяКоордината.У = -50;
НоваяКоордината.З = 0;

Это квадрат в трёхмерном пространстве.

Когда я дошёл до рисования куба, терпеть это надоело и его координаты я рассчитал…  преобразуя числа в двоичную систему счисления. Это глупо, но это было первым, что пришло в голову на тот момент и это работает, а также помогает сократить код за счёт отказа от прописывания координат вручную. У нас ведь три оси, а вершин у куба восемь. 24 строки тупого кода против этого:

Для Счетчик = 0 По 7 Цикл
	Результат = "";
	Число = Счетчик;
	Пока Число > 0 Цикл
		Результат = Строка(Число % 2) + Результат;
	  	Число = Цел(Число / 2);
	КонецЦикла;
	
	Пока СтрДлина(Результат) < 3 Цикл
		Результат = "0" + Результат;
	КонецЦикла;
	
 	НоваяКоордината = ТаблицаКоординат.Добавить();
	НоваяКоордината.Х = ?(Лев(Результат, 1) = "0", -40, 40);
	НоваяКоордината.У = ?(Прав(Лев(Результат, 2), 1) = "0", -40, 40);
	НоваяКоордината.З = ?(Прав(Результат, 1) = "0", -40, 40);
КонецЦикла;

Если покрутиться вокруг этих координат, получится вот так:

Некоторые коллеги не сразу поняли что это, поэтому на всякий случай поясню: каждая вершина соединена с каждой вершиной прямой линией. Почему? Потому что могу, да и было интересно как это будет выглядеть.

Далее я решил нарисовать шар и тут как раз пригодилась задача с часами. Нам нужно нарисовать часы и каждый час заполнить перпендикулярными им часами. Не знаю, как объяснить точнее. Вот код, а под ним результат.

А = 0;
Пока А <= 3 Цикл //На анимации это значение больше
	Б = 0;
	Пока Б <= 7 Цикл //На анимации это значение больше
		НоваяКоордината = ТаблицаКоординат.Добавить();
		НоваяКоордината.Х = (70 * Sin(А) * Sin(Б));
		НоваяКоордината.У = (70 * Sin(А) * Cos(Б));
		НоваяКоордината.З = (70 * Cos(А));
		Б = Б + 0.2;
	КонецЦикла;
   	А = А + 0.1;
КонецЦикла;

70 это длина стороны треугольника, или радиус шара.

Тут я его разукрасил и покрутился вокруг него:

На моём железе такой скорости отрисовки с такой детализацией добиться нельзя, поэтому гифка редактировалась вручную, отсюда и вотермарка.

Самое интересное заключается в том, что нашу фигуру необходимо вывести на дисплей, а он ни разу не трёхмерный. Всё что у нас есть — это табличный документ и он не в курсе, что такое ось z. Поэтому координаты необходимо перевести из трёхмерного пространства в двухмерное. По специальности я не настоящий сварщик, а радиоинженер и в университете из программирования изучал только делфи на уровне конкатенации строк и ассемблер, который в данной задаче вообще не помощник. Я примерно помню, что в геометрии можно всё вертеть с помощью матриц, но изучал их около месяца, да и то на первом семестре. В общем, сделал как смог:

Рад = 3.1415926535897932/180;
Для Каждого Точка Из ТаблицаКоординат Цикл
	Х = -1 * Точка.Х * Sin(Горизонт * Рад) + Точка.З * Cos(Горизонт * Рад);
       У = -1 * (Точка.Х * Cos(Горизонт * Рад) + Точка.З * Sin(Горизонт * Рад)) * Sin(Вертикаль * Рад) + Точка.У * Cos(Вертикаль * Рад);
	НоваяТочка = КоординатыЭкрана.Добавить();
	НоваяТочка.Х = Х + 75;
	НоваяТочка.У = У + 75;
КонецЦикла;

Если не умножать результат на -1, мы будем не вращать объект, а сжимать его. Смещение координат сделано по той причине, что фигуры рисовались в начале трёхмерного пространства, т.е. точка 0;0;0 находится внутри фигуры. Без этого смещения в табличный документ попадёт только четверть фигуры.

У нас есть два ползунка, которые отвечаю за углы, с которых мы смотрим на наш объект. Мне показалось, это проще чем крутить сам объект — так его координаты остаются неизменными. Перемещаемся только мы, относительно него. Получается, наш объект находится внутри сферы, по границе которой мы двигаемся. Всё вернулось к задаче со стрелками часов в более сложном исполнении. Теперь мы получаем на выходе проекции точек из трёхмерного на двухмерное пространство, которые можно вывести в табличный документ, или не в табличный документ. Единственным минусом данного метода является топорная проекция, не имеющая перспективы, что особенно хорошо заметно на пирамиде. За счёт того, что все окружающие объекты мы привыкли видеть в перспективе, при вращении кажется, что тыльная сторона основания шире фронтальной. Поэтому если кто-то подскажет как сделать преобразование координат с учётом перспективы, я буду очень благодарен.

Все моменты я описал, но на всякий случай выложил обработку, которая умеет генерировать геометрические фигуры в трёхмерном пространстве и выводить на экран. Она тестировалась на платформе 8.3.10. В ней присутствует удобное управление углами наклона, привязанное к клавишам WASD. Также есть кнопка "Демо", запускающая автоматическое вращение текущего объекта. Вращение шара будет происходить медленнее, это сделано специально чтобы исключить зависание.

16

Скачать файлы

Наименование Файл Версия Размер
Работа с трёхмерными объектами штатными средствами
.epf 10,85Kb
30.07.18
5
.epf 10,85Kb 5 Скачать

См. также

Комментарии
Сортировка: Древо
1. HAMMER_59 70 31.07.18 08:09 Сейчас в теме
У меня только один вопрос: "Почему перед тем как изобретать колесо, Вы не прочитали теорию по компьютерной графике".
Это ведь самые азы компьютерной графики, это как 2 + 2.
Какое же это 3Д если объекты при удалении не уменьшаются?
Почему мы видим грани которые не должны видеть, и они никак особо не отмечены?
Косинус и Синус не дешевые операции, а Вы их для каждой точки вычисляете, конечно все тормозит.

Тут даже не компьютерная графика еще в древнем мире объемный куб изображали так.


А 1С-ники до этого еще не дошли, печаль.
2. Неопределено 39 31.07.18 10:05 Сейчас в теме
(1)
Какое же это 3Д если объекты при удалении не уменьшаются?

3D -- это пространство с тремя осями координат. Их здесь три, просто в той проекции, которую я использую, нет перспективы, о чём я написал в статье. Объёмная фигура остаётся объёмной в своём виртуальном трёхмерном пространстве, но проецируется на экран она без учёта расстояния до каждой точки, что не мешает воспринимать её как объёмную фигуру и не делает её не трёхмерной. Это проблема метода проекции, а не виртуального объёма. Я не ставил перед собой цель научить как делать правильно, а просто хотел сказать "народ, я этого не видел раньше, но вот так тоже можно в 1С, посмотрите, вдруг понадобится, в этом направлении тоже можно развивать идеи". Я просто выбрал интересную для себя задачу и решил её так, как я умел, чтобы отдохнуть от регистро-отчётной рутины. Мне было интересно сделать это самостоятельно, размять мозги, подумать в новом для себя направлении без посторонней помощи. Меня этому не учили и поэтому меня это привлекло. Я сторонник идеи "используй готовую библиотеку", но эта статья -- не решение проблемы, а попытка расширить кругозор, сказать что 1С умеет больше, чем мы привыкли. Сказать это своими словами, а не автора учебника по компьютерной графике. В конце концов, в завершении я написал что буду благодарен за описание работы с трёхмерными объектами с помощью матриц. Я примерно представляю что так можно сделать, но это очень далеко от моей специализации.

еще в древнем мире объемный куб изображали так

Вот вы пишете что у меня не 3D, а я могу то же самое написать про этот куб. Или это прямоугольный параллелепипед? Или усечённая пирамида? Или квадрат с рисунком? Или труба с квадратным сечением? Это проблема удобства восприятия. Я сделал его удобнее. Не идеальным, но удобнее чем никак и в статье я написал, что можно сделать лучше, просто я в силу своих способностей пока не могу так сделать.
Dementor; Gang031; AlexGroovy; CyberCerber; Alias; rintik; +6 Ответить
10. HAMMER_59 70 31.07.18 14:01 Сейчас в теме
(2)
Вот вы пишете что у меня не 3D, а я могу то же самое написать про этот куб. Или это прямоугольный параллелепипед? Или усечённая пирамида? Или квадрат с рисунком? Или труба с квадратным сечением? Это проблема удобства восприятия. Я сделал его удобнее.


Может оно так прозвучало, но я не об этом писал.
Я считаю, что теория компьютерной графики - это очень серьезное достижение, научный труд, система знаний. Это тоже самое что с базами данных, взять и откинуть весь накопленный опыт, и начать работать напрямую с двоичными файлами.
Не просто так рассматриваются все преобразования на плоскости. Этому есть понятная причина - восприятие такого материала намного проще.
И после правильно изложенного материала на плоскости, переход в 3-х мерному пространству крайне прост. Фактически появляется ось Z, которая расположена по центру экрана и направлена в глубь экрана. Матрицы преобразований остаются практически такими же, конечно с учетом появившейся координаты. Т.е. изменения в коде минимальны, все работает точно так же.

И если нет изометрической проекции, определения передней и задней части грани, что тогда нового, о чём тут рассказывать, чем это отличается от 2Д?
21. Неопределено 39 01.08.18 06:57 Сейчас в теме
(10)
чем это отличается от 2Д?

Всем:

Слева 3D, справа 2D.
22. HAMMER_59 70 01.08.18 08:19 Сейчас в теме
(21)
По мне так в обоих случая 3Д, просто геометрические фигуры разные.

Зачем выдергивать фразу из контекста?
Я ведь написал не как визуально выглядит, а про математическую модель. И в следующей статье, я покажу, что ничего менять даже в коде не надо, чтобы перейти от 2Д к 3Д. Матрицы преобразований станут 4х4, а не 3х3, но заполняться они будут абсолютно точно также.

Т.е. это самая настоящая декомпозиция, из сложной задачи, мы получили несколько простых. А в случае перехода к 3Д, даже никаких усложнений не произойдет. Конечно, пока не введем новые преобразования, но это именно будут уже новые преобразования.
23. Неопределено 39 01.08.18 09:47 Сейчас в теме
(22) Показывайте. Никто же не против. Я ведь уже объяснил: я просто придумал задачу и решил её своим путём. Почему-то так получилось, что одновременно с этим вы решили написать статью на ту же тему и хотите сделать её своим путём. Вы выбрали матрицы, а я выбрал треугольники. Я сделал как смог, без подготовки. Вы хотите сделать как по вашему мнению правильнее, имея знание теории. Это же наоборот здорово. Людям будет с чем сравнить.
24. HAMMER_59 70 01.08.18 10:19 Сейчас в теме
(23) В чем предмет спора?

Я высказал свое мнение, что прежде чем решать задачу, стоит поискать накопленный опыт. В случае с компьютерной графикой, такой опыт есть, информация крайне доступна. Это 20 лет назад, были проблемы с интернетом, документация сплошь на английском. А сейчас всё очень доступно.

А Вам вот захотелось так - это Ваше право. Я всего лишь высказал свое мнение, что, на мой взгляд, есть вариант проще и эффективней.
25. Неопределено 39 01.08.18 10:44 Сейчас в теме
(24)
В чем предмет спора?

Я и не спорю.

Я всего лишь высказал свое мнение

И я каждый раз согласился с ним за исключением того момента, что это не 3D. Просто не смотря на то что я с вами соглашаюсь, вы раз за разом повторяете что я делаю неправильно, хотя все и так всё поняли с первого раза.
4. CyberCerber 213 31.07.18 10:41 Сейчас в теме
(1) Интересные вещи на ИС происходят, как-то одновременно появилось несколько авторов, занимающихся графикой, так у них еще и полемика начинается.
Прямо 1С-ные компьютерно-графичные войны!

Вообще, я рад этому, тема интересная, и даже иногда нужная. Сам занимался задачей упаковки, рисовал коробки методом, что был описан в статье Ильдаровича, а для трехмерной визуализации использовал всякие внешние сервисы. А вот, оказывается, можно и в 1С сделать.
5. Неопределено 39 31.07.18 10:44 Сейчас в теме
(4)
Прямо 1С-ные компьютерно-графичные войны!

Конкуренция - двигатель прогресса. Сейчас коробки заполним, потом, глядишь, ячейки на складах визуализируем.
17. pm74 126 31.07.18 21:15 Сейчас в теме
(4)
Прямо 1С-ные компьютерно-графичные войны!

действительно забавно получается .
заметил , что есть тенденция массовой публикации статей по схожей тематике , что то вроде цепной реакции
7. ivanov660 817 31.07.18 12:10 Сейчас в теме
(1)Коллега прежде чем ругаться почитали бы сами немного теорию по компьютерной графике. Есть проекция изометрическая, а есть ортографическая. В учебниках по азам OpenGL, DirectX это идет в первых главах. Автор как раз нам и продемонстрировал вариант ортографической проекции.
8. HAMMER_59 70 31.07.18 12:36 Сейчас в теме
(7) Знание Вами теории нужно еще проверять, подозреваю только что поисковиком и нашли термины о которых раньше и не слышали.
Если отбросить все лишнее останется только: коллега просто отбросил координату Z при выводе изображения на экран. Ну мягко говоря, так себе 3Д.
Подозреваю что на банальный вопрос в чем отличие Direct 3D от Open GL не сможете дать ответ, а я могу и поглубже копнуть, намного глубже.
12. ivanov660 817 31.07.18 14:54 Сейчас в теме
(8)1. Сомневаюсь, что человек не знакомый с работой 3д графики обладает данными понятиями. К тому же, чтобы что-то найти надо знать что искать.
А так мне довелось заниматься работой с графикой до работы в 1С, на протяжении 10 лет.
Думаю вам знакомы понятия GLUT, GL_TRIANLE, z-buffer, стенсельные и объемные тени, GLSL (вертексные и пиксельные шейдеры),VertexBufferArrayи т.д.
2. Мериться размерами знаний просто так не вижу смысла. Вот если бы вы поставили на кон что-то ;-)
3. В свое время, когда изучал графику, мне Dircet не пришелся по вкусу 5,6 версии были очень сложными в понимании и только с 9-й версии появилось удобство в работе как с OpenGL. Думаю что в качестве основного отличия будем считать программный интерфейс и поддержку видеокартами специфики команд расширения. Ну, и директы доступны, только под виндой.
13. HAMMER_59 70 31.07.18 15:23 Сейчас в теме
(12)
Думаю вам знакомы понятия GLUT, GL_TRIANLE, z-buffer, стенсельные и объемные тени, GLSL (вертексные и пиксельные шейдеры),VertexBufferArrayи т.д.


Из всего вышеперечисленного знаю только z-buffer.

Компьютерная графика для меня так осталась только хобби, и довольно быстро пришло понимание, для того чтобы сделать что-либо стоящее нужно очень много ресурсов, т.е. без разделения труда никак, и в свободное время много не сделаешь. Реальность меня как-то сразу подтолкнула к выбору в сторону 1С.
14. ivanov660 817 31.07.18 15:33 Сейчас в теме
(13)Сейчас на самом деле пора собственных движков прошла и эти знания по сути не нужны.
Достаточно взять готовый фреймворк. К примеру, самый простой и удобный Unity3d. Тут есть и прекрасный IDE, и набор плагинов и вообще прикольная штука.
Написать мобильное приложение для меня приятнее в нем, нежели в EDT или конфигураторе.
20. HAMMER_59 70 01.08.18 06:37 Сейчас в теме
(14) Я смотрю на графику с другой точки зрения. Для меня представляет интерес - математическая модель.
Мне реально интересно как с помощью математики, физики можно смоделировать модель реального мира.
К сожалению на практике нигде я это все применить не могу, как-то не особо востребованы такие знания.
С другой стороны 1С тоже ведь моделирует хозяйственную деятельность.

Еще добавлю, чем меня восхищают графические движки, они ведь не точную модель строят, а приближенную, но при этом выглядит реалистично, современную 3Д графику которая на ходу рендерит, пускай даже 60 кадров, уже не отличить от видео. Реальный мир ведь не из треугольников состоит, а свет из просто гигантского числа фотонов, которые еще и ведут себе не линейно.
27. WalterMort 279 02.08.18 13:49 Сейчас в теме
(14) Достаточно долго занимаюсь Unity и эти знания очень даже нужны. Особенно если пишешь плагин, а что-то серьезное без своих плагинов не напишешь.
28. ivanov660 817 02.08.18 14:01 Сейчас в теме
(27)всегда можно купить, у них замечательный магазин.
По опыту, пробовал писать 2d скроллеры, все что нужно есть, кодил только логику и поведение.
9. HAMMER_59 70 31.07.18 13:20 Сейчас в теме
(7) Если придираться то DirectX включает Direct3D, и в книгах по DirectX, как раз про Direct3D не пишут.
Но я ведь не об этом писал. Я писал, что теория компьютерной графики и для OpenGL, и для Direct 3D она везде одинаковая.

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

Лично я бы хотел, чтобы Инфостарт был познавательным ресурсом, а не развлекательным.
11. ivanov660 817 31.07.18 14:39 Сейчас в теме
(9)Соглашусь в том, что данный пример не несет смысловой нагрузки. Пример можно рассматривать как забавный пример, эксперимент или что-то в данном духе.
19. SlavaKron 01.08.18 06:37 Сейчас в теме
(7) Разве изометрическая не является вариантом ортографической?
29. Неопределено 39 03.08.18 08:56 Сейчас в теме
(19)
Если посмотреть на картинку с википедии, становится понятно что изометрия, диметрия и триметрия являются частными случаями аксонометрии. Про ортографию я не нашёл ни слова, но есть схожее с аксонометрической проекцией описание на других ресурсах. Поэтому, если это одно и то же, понятие изометрической проекции уместно для чертежа на бумаге, но не для объёмной фигуры, на которую можно смотреть с любой стороны. Но в целом да, получается что изометрическая проекция это частный случай ортографической, который мы увидим, наблюдая фигуру под строго определёнными углами. А в целом этот тип проекции с построением параллельных линий википедия зовёт аксонометрической проекцией.
3. madonov 159 31.07.18 10:36 Сейчас в теме
6. Неопределено 39 31.07.18 10:44 Сейчас в теме
15. Casey1984 3 31.07.18 17:57 Сейчас в теме
(6) Финальные боссы - ФНС, ПФР и Меркурий ;-)
26. madonov 159 02.08.18 04:55 Сейчас в теме
(15) ЕГАИС, 6-НДФЛ, Онлайн-Кассы, смена ставки НДС...
16. MuI_I_Ika 502 31.07.18 18:14 Сейчас в теме
Автор жги. Никого не слушай
18. Неопределено 39 01.08.18 02:00 Сейчас в теме
(16) Спасибо, давно не виделись (я Golickoff с сам знаешь какого форума).
30. banch46 6 03.08.18 10:10 Сейчас в теме
Добрый день. что то я не понял. Это сделано штатными средствами без использования компонент? А что за объект используется "ТаблицаКординат" и куда производится вывод?
31. Неопределено 39 03.08.18 10:48 Сейчас в теме
(30) Здравствуйте. Да, исключительно штатными средствами. ТаблицаКоординат -- это таблица значений с реквизитами Х, У и З, имеющими тип число. Всё выводится в табличный документ, но это сделано просто потому что у меня был готовый шаблон обработки. Как я написал в статье, вывод можно осуществлять в векторном, а также в растровом форматах. Здесь я просто хотел показать что так в принципе можно делать. Ниже привёл скриншот обработки, открытой в конфигураторе
Оставьте свое сообщение