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

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

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

Kadet

Добрый день! В своей работе в последнее время часто использую подобный макрос:

Sub Main()
Dim Coordinates(4) As New com.sun.star.awt.Point

Coordinates(0).x = 0
Coordinates(0).y = 0
Coordinates(1).x = 0
Coordinates(1).y = 1000
Coordinates(2).x = 1000
Coordinates(2).y = 1000
Coordinates(3).x = 1500
Coordinates(3).y = 1500
Coordinates(4).x = 1000
Coordinates(4).y = 0

DrawFigura(Coordinates)

End Sub

'***************************************************************************************************************
Sub DrawFigura(Coordinates)
Dim xDoc, index%, width, color&, Fillcolor&, sName$, fShad, iLayer%, iLineDash&
Dim xPage as object, xShape as object, PolyPolygon As Variant
Dim aPosition As New com.sun.star.awt.Point
Dim TheSize As New com.sun.star.awt.Size
Dim oLineDash As New com.sun.star.drawing.LineDash

xDoc = ThisComponent
xPage = xDoc.DrawPages(0)
' Первая линия ********************************
xShape = xDoc.createInstance("com.sun.star.drawing.PolyPolygonShape") ' Многоугольник

xShape.Shadow = fShad
xShape.LineColor = color
xShape.LineWidth = width
xShape.FillColor = Fillcolor
xShape.LayerID = iLayer '(1)-Задвинуть за текст; (0)-Перед текстом
'*************************************************************************************
xPage.add(xShape)
xShape.PolyPolygon = Array(Coordinates())

End Sub

Эта процедура рисует пространственный многоугольник, плоский, двумерный. (В данном случае все значения набросаны от балды и могут не работать).
В этом многоугольнике можно установить большое количество точек (задаются с помощью массива Coordinates()).

Так вот. К чему бишь я. В описаниях библиотеки drawing ещё имеются описания таких объектов как PolyPolygonShape3D и Position3D. Последний просто задаёт трёхмерную координату (x,y,z), типа Point в двумерном мире - Position3D (описание). А вот с PolyPolygonShape3D (описание)  никак не могу разобраться. Указывается, что оно задаёт трёхмерные координаты трёхмерного многоугольника, НО не создаёт его. Когда я пытаюсь воспользоваться им по аналогии с PolyPolygonShape, т.е. - xShape = xDoc.createInstance("com.sun.star.drawing.PolyPolygonShape3D") получаю объект NULL. Если я пытаюсь использовать его по аналогии с: Dim aPosition3D As New com.sun.star.awt.Point, т.е. - Dim aPosition3D As New com.sun.star.awt.PolyPolygonShape3D, то получаю объект, в методах которого имею Name и Parent и всё. Никаких тебе координат и т.п.

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

Заранее благодарен.

economist

Тема процедурного рисования/проектирования в LO будет ох непроста. Всякий раз возникает мысль нарисовать в чем-то снаружи и вставить уже готовый образмеренный PNG в чертежном стиле. Все эти nanoCAD/OpenCAD/EasyCAD такое умеют. И там легко и проекции/сечения выдать, и готовый объемный сметный расчет итд итп.

Вложил небольшую книжицу по макросам Basic для графики, вдруг не боян.
Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...

Kadet

Спасибо! Ща буду изучать. Может поможет.

Я проштудировал CADы и САПРы. В частности, была возможность поюзать Компас3D. Глубоко и весьма сложно. Все CADы нацелены на скурпулёзное и детальное черчение с вычерчиванием всех мелочей и т.п. Для тех задач, которые я решаю это несколько излишне. По крайней мере на данном этапе. Нужен быстрый и лёгкий способ набрасывать конструкцию из заранее заложенных элементов.
Есть такая программка Ковка3D. Есть много роликов по ней, как ею пользоваться. Она сделана на базе СorelDrow. Вот, хочу сварганить нечто подобное. Простенько, быстро и доступно.

Kadet

Вот образец того, к чему я стремлюсь - Ковка3D

economist

Тогда к выбору инструмента точно нужно подойти взвешенно. В CorelDraw используется VBA, код оттуда успешно люди портируют на Python в InkScape, который "тот же 9-й корел, тока свободный". О разработке расширений https://inkscape.org/develop/extensions/
Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...

Kadet

Научился создавать 3D объекты.
xShape3D = xDoc.createInstance("com.sun.star.drawing.Shape3DSceneObject") ' Объёмный объект

Есть ещё объёмные фигуры. Ща буду разбираться как создавать и в чём различия между "фигурами" и "объектами".

Kadet

Ещё нашёл много объектов 3D.
'com.sun.star.drawing.RectangleShape 'Прямоугольная форма
'com.sun.star.drawing.Shape3DCubeObject 'Форма 3D Кубический объект
'com.sun.star.drawing.Shape3DExtrudeObject 'Форма 3D Выдавливание Объекта
'com.sun.star.drawing.Shape3DLatheObject 'Форма 3D-объекта токарного станка
'com.sun.star.drawing.Shape3DPolygonObject 'Форма 3D Полигонального объекта
'com.sun.star.drawing.Shape3DSceneObject 'Форма объекта 3D Сцены
'com.sun.star.drawing.Shape3DSphereObject 'Форма 3D-объекта Сферы

Есть поля для исследования.

Kadet

Добрый день!
Помогите разобраться с формированием и заполнением многомерных массивов.

Для формирования 3D-объекта создал такой макрос (набросок, схематично):
'***************************************************************************************************************
Sub Draw3Dobject()
Dim xDoc, index%, Xpoz&, Ypoz&, Xsm&, Ysm&, Xs&, Ys&, width, color&, Fillcolor&, sName$, fShad, iLineDash&, Obj1
Dim xPage as object, xShape as object, PolyPolygon As Variant
Dim aPosition As New com.sun.star.awt.Point
Dim TheSize As New com.sun.star.awt.Size
Dim oLineDash As New com.sun.star.drawing.LineDash
Dim Coordinates(4) As New com.sun.star.awt.Point
Dim aPosition3D(7) As New com.sun.star.drawing.Position3D
Dim Sequence(7) As New com.sun.star.drawing.PolyPolygonShape3D

xDoc = ThisComponent
xPage = xDoc.DrawPages(0)
xShape3D = xDoc.createInstance("com.sun.star.drawing.Shape3DPolygonObject") ' Многоугольник

xPage.add(xShape3D)

xShape.Shadow = fShad
xShape.LineColor = color
xShape.LineWidth = width
aPosition.X = Xpoz
aPosition.Y = Ypoz
xShape.setPosition(aPosition)
xShape.FillColor = Fillcolor

End Sub


При создании объекта на странице (xPage.add(xShape3D)) в объекте создаётся структура - xShape3D1.D3DPolyPolygon3D, которая представляет из себя многомерный массив типа com.sun.star.drawing.PolyPolygonShape3D. Насколько я понимаю, по аналогии с плоскостными фигурами, именно в этот массив и необходимо вносить данные для формирования очертаний созданного объекта. Однако, как вносить или изменять данные в этом массиве никак не могу разобраться.
Есть ещё два, почти однотипных объекта Shape:
xShape3D1 = xDoc.createInstance("com.sun.star.drawing.Shape3DExtrudeObject") ' Форма 3D Выдавливание Объекта
xShape3D2 = xDoc.createInstance("com.sun.star.drawing.Shape3DLatheObject") ' Форма 3D-объекта токарного станка (объект вращения)

Там уже при создании объекта на странице создаётся массив следующего вида:
D3DPolyPolygon3D
SequenceX
SequenceX(0)
SequenceX(0)(0)
SequenceX(0)(1)
SequenceX(0)(2)
SequenceX(0)(3)
SequenceY
SequenceY(0)
SequenceY(0)(0)
SequenceY(0)(1)
SequenceY(0)(2)
SequenceY(0)(3)
SequenceZ
SequenceZ(0)
SequenceZ(0)(0)
SequenceZ(0)(1)
SequenceZ(0)(2)
SequenceZ(0)(3)

Однако, данные в этих массивах никак не могу изменить. Даже прямыми - xShape3D1.D3DPolyPolygon3D.SequenceX(0)(0) = 1000 ничего не меняется.

В плоскостной графике это делается следующим образом:
'***************************************************************************************************************
Sub DrawObject()
Dim xDoc, index%, Xpoz&, Ypoz&, Xsm&, Ysm&, Xs&, Ys&, width, color&, Fillcolor&, sName$, fShad, iLineDash&, Obj1
Dim xPage as object, xShape as object, PolyPolygon As Variant
Dim aPosition As New com.sun.star.awt.Point
Dim TheSize As New com.sun.star.awt.Size
xDoc = ThisComponent
xPage = xDoc.DrawPages(0)
xShape = xDoc.createInstance("com.sun.star.drawing.PolyPolygonShape") ' Многоугольник

xPage.add(xShape)

xShape.Shadow = fShad
xShape.LineColor = color
xShape.LineWidth = width
aPosition.X = Xpoz
aPosition.Y = Ypoz
xShape.setPosition(aPosition)
xShape.FillColor = Fillcolor
'*************************************************************************************
Coordinates(0).x = 0
Coordinates(0).y = 0

Coordinates(1).x = 4000
Coordinates(1).y = 0

Coordinates(2).x = 4000
Coordinates(2).y = 4000

Coordinates(3).x = 0
Coordinates(3).y = 4000

Coordinates(4).x = 0
Coordinates(4).y = 0

xShape.PolyPolygon = Array(Coordinates())
End Sub

И всё работает.
А с заполнением трёхмерного сложного массива никак не разберусь.
Помогите, пожалуйста, разобраться с этой проблемой.

Kadet

Попробовал такой финдиперс:
Dim Sequence As New com.sun.star.drawing.PolyPolygonShape3D
Dim SequenceX(3) As Double
Dim SequenceY(3) As Double
Dim SequenceZ(3) As Double

oPole = xShape3D1.D3DPolyPolygon3D
SequenceX = Array(1000,5000,5000,1000)
SequenceY = Array(1000,1000,5000,5000)
SequenceZ = Array(1000,1000,5000,5000)

Sequence.SequenceX = Array(SequenceX)
Sequence.SequenceY = Array(SequenceY)
Sequence.SequenceZ = Array(SequenceZ)

xShape3D1.D3DPolyPolygon3D.SequenceX(0) = Array(SequenceX)
xShape3D1.D3DPolyPolygon3D.SequenceY(0) = Array(SequenceY)
xShape3D1.D3DPolyPolygon3D.SequenceZ(0) = Array(SequenceZ)

oPole = Array(Sequence)
xShape3D1.D3DPolyPolygon3D = Array(Sequence)


Теперь массив Sequence начал принимать аргументы. И даже массив oPole, тоже.
А вот сам объект - xShape3D1.D3DPolyPolygon3D = Array(Sequence) никак не хочет принимать данные. Даёт ошибку.

sokol92

Интерфейс drawing.Shape3DPolygonObject в API 6.4 не описан и, похоже, работы ведутся (хотя, могу сказать очередную глупость  ;) ).

Д-р MRI сообщает, что свойство D3DTexturePolygon3D является структурой типа .drawing.PolyPolygonShape3D, значит, в Вашем коде присвоение должно выглядеть так:

xShape3D1.D3DPolyPolygon3D=Sequence
Владимир.

Kadet

Цитата: sokol92 от  7 июля 2021, 16:33xShape3D1.D3DPolyPolygon3D=Sequence
Да, вы правы. Я пробовал. Не получалось. Не получалось, потому что пытался засовывать многомерный массив, и получается, что не правильно сформированный.

Сейчас сделал так:
SequenceX = Array(0, 5000, 5000, 0)
SequenceY = Array(0, 0, 5000, 5000)
SequenceZ = Array(0, 0, 0, 0)

Sequence1.SequenceX = Array(SequenceX)
Sequence1.SequenceY = Array(SequenceY)
Sequence1.SequenceZ = Array(SequenceZ)

xShape3D.D3DPolyPolygon3D = Sequence1

И, вроде бы, данные изменились,.. правда на странице ничего не появилось, но уже.. определённый прогресс. Спасибо.
Это получается - сформировался 0-й полигон. А вот теперь как туда добавить - 1-й, 2-й, 3-й. Т.е. нужно сделать массив типа - Array(6)(4), а такую запись вроде бы LO не пропускает. А если сделать массив вида - Array(6,4), то он не входит по параметрам в структуру D3DPolyPolygon3D.
Интересно, можно ли к структуре D3DPolyPolygon3D  применить ReDim по первой размерности?

Kadet

Должно по идее получаться следующая структура (допустим):
Sequence1.SequenceX(0)(0)
Sequence1.SequenceX(0)(1)
Sequence1.SequenceX(0)(2)

Sequence1.SequenceY(0)(0)
Sequence1.SequenceY(0)(1)
Sequence1.SequenceY(0)(2)


Sequence1.SequenceZ(0)(0)
Sequence1.SequenceZ(0)(1)
Sequence1.SequenceZ(0)(2)

....
Sequence1.SequenceX(1)(0)
Sequence1.SequenceX(1)(1)
Sequence1.SequenceX(1)(2)

Sequence1.SequenceY(1)(0)
...
Sequence1.SequenceZ(1)(0)
...

Т.е. менять нужно первую  разрядность подуровня структуры PolyPolygonShape3D
Пока не могу понять как.

sokol92

#12
Размерность Sequence1.SequenceX (и др) определяется как (0 to 0) в силу того, что Вы присваиваете массив, определенный оператором Array с одним аргументом.

Присваивайте так (схема):

Sequence1.SequenceX = Array(SequenceX, SequenceX1, SequenceX2) ' ... размерность (0 to 2)

Например (константы произвольные):

Sequence1.SequenceX=Array( Array(1000,5000,5000,1000), Array(2000,6000,6000,2000), Array(3000,7000,7000,3000))
Владимир.

Kadet

#13
Ну, можно, конечно и так. Спасибо!
Я придумал немного по-другому. Таки загнал туда данные.
Sub Draw3Dobject11()
Dim xDoc, index%, Xpoz&, Ypoz&, Xsm&, Ysm&, Xs&, Ys&, width, color&, Fillcolor&, sName$, fShad, iLineDash&, Obj1
Dim xPage as object, xShape as object, PolyPolygon As Variant
Dim aPosition As New com.sun.star.awt.Point
Dim TheSize As New com.sun.star.awt.Size
Dim Sequence As New com.sun.star.drawing.PolyPolygonShape3D
Dim SequenceX(3) As Double
Dim SequenceY(3) As Double
Dim SequenceZ(3) As Double
Dim SequenceX1(5)
Dim SequenceY1(5)
Dim SequenceZ1(5)
'********************************************************
xDoc = ThisComponent
xPage = xDoc.DrawPages(0)

xShape3D = xDoc.createInstance("com.sun.star.drawing.Shape3DPolygonObject") ' Форма 3D Полигонального объекта
xPage.add(xShape3D)

SequenceX = Array(0, 5000, 5000, 0)
SequenceY = Array(0, 0, 5000, 5000)
SequenceZ = Array(0, 0, 0, 0)

SequenceX1(0) = SequenceX
SequenceY1(0) = SequenceY
SequenceZ1(0) = SequenceZ

SequenceX = Array(0, 0, 5000, 5000)
SequenceY = Array(0, 0, 0, 0)
SequenceZ = Array(0, 5000, 5000, 0)

SequenceX1(1) = SequenceX
SequenceY1(1) = SequenceY
SequenceZ1(1) = SequenceZ

SequenceX = Array(0, 0, 0, 0)
SequenceY = Array(0, 0, 5000, 5000)
SequenceZ = Array(0, 5000, 5000, 0)

SequenceX1(2) = SequenceX
SequenceY1(2) = SequenceY
SequenceZ1(2) = SequenceZ

SequenceX = Array(5000, 5000, 5000, 5000)
SequenceY = Array(0, 0, 5000, 5000)
SequenceZ = Array(0, 5000, 5000, 0)

SequenceX1(3) = SequenceX
SequenceY1(3) = SequenceY
SequenceZ1(3) = SequenceZ

SequenceX = Array(0, 0, 5000, 5000)
SequenceY = Array(5000, 5000, 5000, 5000)
SequenceZ = Array(0, 5000, 5000, 0)

SequenceX1(4) = SequenceX
SequenceY1(4) = SequenceY
SequenceZ1(4) = SequenceZ

SequenceX = Array(0, 5000, 5000, 0)
SequenceY = Array(0, 0, 5000, 5000)
SequenceZ = Array(5000, 5000, 5000, 5000)

SequenceX1(5) = SequenceX
SequenceY1(5) = SequenceY
SequenceZ1(5) = SequenceZ

Sequence.SequenceX = SequenceX1
Sequence.SequenceY = SequenceY1
Sequence.SequenceZ = SequenceZ1

xShape3D.D3DPolyPolygon3D = Sequence
aPosition.X = 5000
aPosition.Y = 2000
xShape3D.setPosition(aPosition)
xShape3D.HoriOrientPosition = 5000
xShape3D.VertOrientPosition = 2000

xShape3D.Shadow = fShad
xShape3D.LineColor = color
xShape3D.LineWidth = width
aPosition.X = Xpoz
aPosition.Y = Ypoz
xShape3D.setPosition(aPosition)
TheSize.width = Xsm
TheSize.height = Ysm
xShape3D.FillColor = Fillcolor
xShape3D.setSize(TheSize)

End Sub

Данные, таки загнать удалось, однако на странице ничего не отобразилось. Хотя объект по индексу находится, значит существует.
Теперь буду разбираться с этой проблемой.

Делал в Drow всякие трёхмерности, сразу или преобразовывал, вне зависимости от способа на странице однозначно появляются объекты типа:
xShape3D = xDoc.createInstance("com.sun.star.drawing.Shape3DSceneObject") ' 3D-сцена
Видимо, для того, чтобы отобразить 3D объект эти вот полигоны, с которыми пришлось помучится, нужно преобразовать в 3D-сцену. 3D-сцена, насколько я понял, есть совокупность 3D-объектов, полигонов и пр.
Однако, пока не могу найти способ преобразования 3D-объектов в 3D-сцену.
А в самой 3D-сцене я так и не нашёл хоть какие-нибудь ссылки на какие-нибудь объекты из которых состоит эта сцена. В ней только фокусы, массивы трансформации, освещённости, камеры и т.п. Нужная вещь, но... не сейчас.

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

Kadet

#14
Меня сегодня осенило и я всё понял с этими 3D-объектами.
Значит. Азы.

Любой Draw-объект в LO должен быть заключёт в некий свой фрейм. Однако, если для плоскостных объектов они, эти фреймы, создаются самой LO автоматически и мы при их программировании не прикладываем никаких дополнительных усилий для этого, то для 3D-объектов для создания этих самых фреймов для 3D-объектов необходимо приложить эти самые усилия, т.е. создавать эти фреймы программно.

Так вот, я никак не мог понять что такое 3D-сцены, почему при создании объектов вручную все объекты автоматически представляются как эти самые сцены, хотя в программировании есть возможности создания и Куб и Сферу и пр. Однако, когда вылавливаешь эти объекты, созданные вручную, по индексу, то все они имеют тип 3D-сцена, а не какие-нибудь другие объекты, которые создавались вручную.
И второй вопрос - почему при создании 3D-объектов программно они не отображаются, хотя по индексу находятся, т.е. - создаются.

Так вот меня и осенило, что именно эти самые сцены и есть те самые фреймы для 3D-объектов, и что сначала нужно создавать эту фрейм-сцену, а потом именно в неё вкладывать создаваемый 3D-объект...

И все пазлы сошлись.
'*** 3D сцена ***********************************************************************************
Sub DrawScene3D()
Dim xDoc, index%, Xpoz&, Ypoz&, Xsm&, Ysm&, Xs&, Ys&, width, color&, Fillcolor&, sName$, fShad, iLineDash&, Obj1
Dim xPage as object, xShape as object, PolyPolygon As Variant
Dim aPosition As New com.sun.star.awt.Point
Dim TheSize As New com.sun.star.awt.Size
Dim aPosition3D As New com.sun.star.drawing.Position3D
Dim aDirection3D As New com.sun.star.drawing.Direction3D
'********************************************************
index = 0
xDoc = ThisComponent
xPage = xDoc.DrawPages(index)
'********************************************************
xScene3D = xDoc.createInstance("com.sun.star.drawing.Shape3DSceneObject") ' Объёмная фигура
xShape3D = xDoc.createInstance("com.sun.star.drawing.Shape3DCubeObject") ' Форма 3D Кубический объект
xPage.add(xScene3D)
xScene3D.add(xShape3D)
'********************************************************
xShape3D.HoriOrientPosition = 5000
xShape3D.VertOrientPosition = 2000
xShape3D.LayerID = 3
aPosition.X = 5000
aPosition.Y = 2000
xScene3D.setPosition(aPosition)
xShape3D.setPosition(aPosition)

TheSize.width = 6000
TheSize.height = 6000
xScene3D.setSize(TheSize)
xShape3D.setSize(TheSize)

End Sub

Одна маленькая фишка - СНАЧАЛА создаётся сцена на странице - xPage.add(xScene3D), а уже потом в эту сцену вкладывается объект - xScene3D.add(xShape3D). В обратном порядке выдаёт ошибку.