Разбираемся с технологией 3D программирования

Автор Kadet, 23 июня 2021, 09:16

0 Пользователи и 1 гость просматривают эту тему.

sokol92

Владимир.

Kadet

#16
Да не за что. Рад поделиться. Может ещё кому пригодится.

Однако, тут ещё исследовать и исследовать.

Выяснил, что координата (0,0,0) находится в центре сцены, а не в углу, как у экрана. Для сцены это весьма удобно, так как именно от нуля пляшут все повороты, масштабирование и т.п.
С координатой Z ещё не до конца разобрался, где конкретно находится её (0).

Так же в одну сцену можно вкладывать несколько (множество) 3D-объектов, а потом посредством возможностей сцены управлять всем этим набором, как единым целым:
'********************************************************
xScene3D = xDoc.createInstance("com.sun.star.drawing.Shape3DSceneObject") ' Объёмная сцена
'********************************************************
xPage.add(xScene3D)
'********************************************************
xShape3D = xDoc.createInstance("com.sun.star.drawing.Shape3DPolygonObject") ' Форма 3D Полигонального объекта
xShape3D1 = xDoc.createInstance("com.sun.star.drawing.Shape3DCubeObject") ' Форма 3D Кубический объект
xShape3D2 = xDoc.createInstance("com.sun.star.drawing.Shape3DExtrudeObject") ' Форма 3D Выдавливание Объекта
xShape3D3 = xDoc.createInstance("com.sun.star.drawing.Shape3DLatheObject") ' Форма 3D-объекта токарного станка
xShape3D4 = xDoc.createInstance("com.sun.star.drawing.Shape3DSphereObject") ' Форма 3D-объекта Сферы
'********************************************************
xScene3D.add(xShape3D)
xScene3D.add(xShape3D1)
xScene3D.add(xShape3D2)
xScene3D.add(xShape3D3)
xScene3D.add(xShape3D4)
'********************************************************

Плоскостные объекты в сцену не вставляются.

Однако, пока не могу разобраться с координатами, размерами и формами этих объектов, внутри сцены. Пытаюсь программировать одно, а выходит совсем не то.
Допустим местоположение и размеры и в сценах и в объектах задаются соответствующими параметрами:
aPosition.X = Xpoz
aPosition.Y = Ypoz
xShape.setPosition(aPosition)
TheSize.width = Xsm
TheSize.height=Ysm
xShape.setSize(TheSize)


А у некоторых объектов, типа Куб, есть ещё дополнительные 3D параметры:
'********************************************************
aPosition3D.PositionX = Xpoz
aPosition3D.PositionY = Ypoz
aPosition3D.PositionZ = Zpoz
xShape3D.D3DPosition = aPosition3D
'********************************************************
aDirection3D.DirectionX = Xsm
aDirection3D.DirectionY = Ysm
aDirection3D.DirectionZ = Zsm
xShape3D.D3DSize = aDirection3D
'********************************************************
'

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

В общем, нужно ещё разбираться и разбираться.

Kadet

#17
С размерами масштабами оказалась засада.
Нужно разбираться.
Размеры и толщины. В общем, мне нужно нарисовать тонкую, ели заметную линию-маркер. Нет, конечно в итоге я буду рисовать её невидимой, но пока я должен её видеть как ориентир. Так вот, так как в 3D-сцену нельзя внедрять плоскостные объект типа "Line", то решил использовать самую простейшую 3D-модель - Куб, с минимально тонкими гранями и рёбрами по двум координатам, но вытянутой по третьей (ну, если линию нужно протянуть по одной координате). Косые линии пока не придумал как делить.
Так вот, делаю куб с рёбрами X=1, Y=1000, Z=1. Толщину линий делаю width=1. Вставляю этот куб в сцену.
В итоге получаю линию, толщиной, по привычным параметрам, где-то width=50, и большей тонкости добиться не могу.

Масштабирование. Делаю сцену величиной с экран. Экран получается следующих размеров - Xmax=33408, Ymax=20320. Т.е. это же и получается - габариты самой сцены. Однако, если пытаюсь нарисовать куб с отклонением от нуля - X=-(Xmax/2), т.е. пытаюсь нарисовать линию в левой части экрана, по сути - в обычной экранной координате X=0, то ничего не вижу.
Эмпирическим путём вычислил, что максимальное отклонение в сцене может быть - X=(-525), т.е. вся ширина сцены составляет где-то (1050), т.е. от (-525) до (+525), это лишь в моём экране, с моим разрешением и при координате Z=0. Думаю, что при изменении этих параметров и размеры сцены могут измениться.
Так же эмпиричным путём вычислил, что в моих условиях 100 единиц в сцене примерно равен 1050 единиц в экранных мерках.

В принципе, эти отклонения для 3D-сцены объяснимы. Ближе - должно выглядеть больше и толще, а дальше - тоньше и меньше. Однако, эксперименты с координатой Z, которая как бы должна отвечать за "ближе/дальше", видимых подтверждений у этих выводов не получаю. Шаг линий и толщины изменяются, но какой-либо логичной системы в этих изменениях пока не получил.

В общем, исследования продолжаются.

В прилагаемом документе "Тест", нужно выполнить макрос DrawScene3D(). Он рисует два вида линий - синие внутри сцены, а чёрные вне сцены. Сцена сделана меньше по Y на 5000ps.
Шаг чёрных линий - 1050ps в экранных единицах, а шаг синих линий - 100ед. в сценарных единицах. Толщина чёрных линий - width=50, а толщина синих линий width=1.
А общем - "найдите три отличия".

P.S.: Исследовал координату Z. Выяснил, что плюсовая координата идёт в сторону смотрящего. Чем ближе, тем толще, шире, больше. Минусовая Z идёт от смотрящего. Но пока упёрся в предел = Z=(-500). Дальше линии пропадают. Видимо это граница сцены в глубину. Буду решать как изменить эту глубину.

Kadet

#18
В общем, "чудеса на виражах" происходят с этими 3D-сценами. Пока мало что понятно.
Однако, следующее.

3D-модель - так будет более стандартно называть простые 3D-объекты, так как чаще именно этот термин используют в инете. Итак, 3D-модель, как выяснилось, всегда принимает размеры сцены, в который её вписывают. И не меняет свои размеры при воздействии на его собственные Position и Size, пока не изменишь размеры самой сцены, под которые и будет смасштабирована и сама модель. Это - если этот объект один в сцене. Однако, при внедрении в эту сцену несколько объектов, то их размеры пропорционально масштабируются относительно габаритов сцены по крайним точкам всех объектов. Надеюсь эта мысль понятна - ищется Xmin и Xmax, а так же Ymin и Ymax у всех вложенных моделей, и относительно этих критичных точек масштабируются все объекты.
Исходя из этого, дабы подогнать координатную сетку сцены под координатную сетку экрана я придумал такую фишку. Создаю два куба-линии по крайним границам Xmax-экрана - один в сценической координате - (-(Xmax/2)), другой в сценической координате - (+(Xmax/2)). При этом координаты и размеры сцены, её объектов становятся идентичны экранным размерам и координатам.
Это делается при Z=0.

В примере я так же обозначил верхнюю и нижнюю границы сцены с помощью прорисовки двух горизонтальных кубов-линий по координатам (-(Ymax/2)) и (+(Ymax/2))

Насколько необходима такая подгонка, я пока не решил. Может быть и не нужна вовсе, но, по крайней мере, она возможна.

Kadet

Такого же результата можно достичь, если по всем четырём углам сцены поставить маленькие, практически невидимые кубики с размерами рёбер (1,1,1).

Kadet

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

Нужно признаться - удобная штука получается.

Интересно теперь узнать, а при поворотах фигуры, где длина объекта, которая идёт по Z, и которая заведомо больше размеров ширины (X) и высоты (Y), будет ли сцена автоматически масштабироваться под длину, в связи со "вновь открывшимися обстоятельствами".

Kadet

#21
Некоторые важные заметки, относительно программирования в 3D.

По-умолчанию глубина сцены небольшая (по оси Z), причём в положительную сторону (к смотрящему) по моим подсчётам влезает 10000ед., а в противоположную сторону всего (-500). Если модель рисуется за пределами этих границ, то она просто не отображается на экране, а сцена не масштабируется.
Чтобы обойти этот момент я увеличиваю параметры сцены "дистанция до сцены" и "фокусное расстояние сцены". Не знаю в чём их разница, но после этого объекты становятся видимыми и сцена сама масштабируется под их размеры.
xScene3D.D3DSceneDistance = 100000 'Дистанция до сцены
xScene3D.D3DSceneFocalLength = 100000 'Фокусная дистанция сцены

По умолчанию эти параметры равны - 10000ед.
Однако, тут есть один совсем непонятный момент. Если эти параметры менять ещё до внедрения в сцену моделей, то они просто не работают. Модели не видимы, масштабирования нет. Но, если внедрить в сцену хотя бы одну модель, а уж потом поменять эти параметры - всё становится видимым и правильно масштабируется. Не понятно почему так, возможно так и задумано, но это так.

Другие важные мелочи.
Направления осей:
Ось ординат Oy - положительное направление вверх, отрицательное вниз.
Ось абсцисс Ox - положительное направление вправо, отрицательное влево.
Ось аппликат Oz - положительное направление - к смотрящему, отрицательное от него.

Координата (0,0,0), как я уже писал, находится относительно в центре сцены... Вернее сказать - где-то в глубине. Но, она какая-то плавающая. Видимо это связано с масштабированием. Допустим если все модели рисовать в положительной (верхней) части по Y, то координата (0,0,0) будет в где-то в нижней части сцены. Если все модели рисовать по положительной части по оси X, то центр (0,0,0) будет где-то слева в сцене.
В общем - гулящий ноль у координатной сетки. Возможно его можно как-то зафиксировать, но пока я не понял как и насколько это нужно.

Kadet

Изменил название темы, под общее русло.

Kadet

Управление проекциями видимости объекта (повороты, вид выше/ниже и т.п.) осуществляется посредством методов D3DCameraGeometry сцены.
Эта структура состоит из трёх видов камер просмотра - vrp, vpn и vup. За что и как отвечает каждая камера пока не разобрался и слабо понимаю.
По-умолчанию имеют следующие значения:
D3DCameraGeometry
vrp
PositionX 0
PositionY 0
PositionZ 10288,57143
vpn
DirectionX 0
DirectionY 0
DirectionZ 288,5714286
vup
DirectionX 0
DirectionY 1
DirectionZ 0

Однако прямое воздействие на значения камер ничего не даёт. Значения не меняются. Нужно менять всю структуру. Для этих целей можно создать переменную типа:
Dim D3DCamera As New com.sun.star.drawing.CameraGeometry
Либо по другому:
D3DCamera = xScene3D.D3DCameraGeometry
Потом в этой переменной меняем нужные значения и засовывает всю структуру обратно. Допустим так:
D3DCamera = xScene3D.D3DCameraGeometry
D3DCamera.vrp.PositionX = 1000
D3DCamera.vrp.PositionY = 1000
D3DCamera.vpn.DirectionX = 1000
D3DCamera.vpn.DirectionY = 1000
xScene3D.D3DCameraGeometry = D3DCamera


И ещё, у меня картинка сразу после изменения параметров камер почему-то не менялась,.. потом менялась,.. потом снова не менялась. В общем вела себя непонятно нестабильно. Способ, когда картинка меняется всегда - восстановить исходные позицию и размеры сцены. При восстановлении картинка обновляется и, соответственно, принимает новые параметры камер:
Dim aPosition As New com.sun.star.awt.Point
Dim TheSize As New com.sun.star.awt.Size
'********************************************************
aPosition = xScene3D.Position
TheSize = xScene3D.Size
'********************************************************
D3DCamera = xScene3D.D3DCameraGeometry
D3DCamera.vrp.PositionX = 1000
D3DCamera.vrp.PositionY = 1000
D3DCamera.vpn.DirectionX = 1000
D3DCamera.vpn.DirectionY = 1000
xScene3D.D3DCameraGeometry = D3DCamera
'...
'********************************************************
xScene3D.setPosition(aPosition)
xScene3D.setSize(TheSize)
'********************************************************


Чтобы провернуть сцену влево нужно в X вводить положительные значения, вправо - отрицательные.
Чтобы провернуть сцену вниз нужно в Y вводить положительные значения, вверх - отрицательные.

Ещё нужно хорошенько исследовать функции камер - vrp, vpn и vup, что за что отвечает и как реагирует на изменения.

Kadet

#24
Судя по всему структура камеры означает следующее:
vrp - имеет тип (com.sun.star.drawing.Position3D), т.е. "позиция", то вероятнее всего эта структура описывает местоположение камеры, т.е. - смотрящего.

Остальные структуры, vpn и vup - имеет тип (com.sun.star.drawing.Direction3D), т.е. "направление", то вероятнее всего эта структура описывает направление камеры, т.е. - куда смотрит смотрящий.
vpn - конкретно описывает координаты точки, куда направлена камера, а вот с vup пока непонятно. Значения по умолчанию - DirectionX = 0, DirectionY = 1, DirectionZ = 0. Что это означает пока не понятно.

mikekaganski

С уважением,
Михаил Каганский

Kadet

#26
Спасибо!
Ну, я правильно разгадал этот ребус:
32 опубликованная структура CameraGeometry
33 {
34     / ** - положение камеры * /
35 год     Position3D vrp;
36
37    / ** - направление обзора камеры * /
38     Direction3D vpn;
39
40    / ** - направление камеры вверх * /
41 год     Direction3D vup;

Однако, третий набор параметров (vup) даже после этого остаётся загадкой. Что такое подразумевается под "направление камеры вверх"? По умолчанию Y=1, а X и Z равны нулю. Т.е., расшифровываю как понял, направление вверх идёт по Y. Видимо предполагается, что "направлением вверх" можно сделать и X и Z?! А возможно и (-Y), (-X), (-Z).
Для чего это нужно пока не представляю, но... есть, значит может пригодиться. Бедум иметь ввиду.

Kadet

А с настройками камеры происходит такая же беда, что и с настройками дистанции и фокуса (xScene3D.D3DSceneDistance). Т.е. пока не повесишь хотя бы одну малюсенькую модельку в сцены, эти все параметры меняй, не меняй... до одного места. Позже они снова выпадают в дефаулт. А может быть, параметры камеры просто обновляются после новых установок дистанции, которые можно менять ТОЛЬКО после внедрения модели в сцену. Точно не вычислил. Но, после внедрения первой модели в сцену все эти параметры лучше установить заново, так как хочется автору, а не дуфоулту.

И ещё.
При включении в сцену новых моделей её размеры могут изменяться без вашего желания. В частности, у меня меняется высота по Y и выходит за границы экрана. По ширине (X) вроде бы фиксировано, не расширяются. Как зафиксировать размеры сцены ещё не смог найти. Однако, вышел их положения восстановлением старых размеров сцены после очередных внедрений моделей. Как это делать описывал выше. Перед внедрением моделей сохраняем параметры Position и Size в переменных, внедряем новые модели, и после восстанавливаем Position и Size сцены из этих переменных. При этом все внедрённые модели пропорционально масштабируются.
Другого пути пока не нашёл.

Kadet

#28
Таки ошибся с определением направлений осей координат X и Y.
Всё таки они привычные:
X - вправо положительные, влево отрицательные.
Y - вверх положительные, вниз отрицательные.

В подпрограмме построения куба (DrawCube3D) не заметил инверсию этих направлений, а на основании неё делал выводы.
Было:
aPosition3D.PositionX = -Xpoz
aPosition3D.PositionY = -Ypoz


Нужно:
aPosition3D.PositionX = Xpoz
aPosition3D.PositionY = Ypoz

В предыдущем посте исправил.

Kadet

#29
Народ, подскажите пожалуйста.
Где найти информацию, хоть какое-нибудь описание о структуре Transformation
Transformation
Line1
Column1 12040
Column2 0
Column3 1719
Line2
Column1 0
Column2 295
Column3 3151
Line3
Column1 0
Column2 0
Column3 1


Что же означают эти Line и Column?
Есть подозрения, что эта инфа мне сейчас нужна.