Es geht um die Strategie der Verwendung von 2D Point und 4D Vector-Koordinaten.
Folgende Ausgangspunkte:
1. Die VectorDrawing Befehle von PureBasic verwenden als Koordinaten bereits Double-Float!
Bei der 2D Drawing Library gibt es dazu keine Angeben, daher gehe ich davon aus, dass es Integer-Werte sind
2. Sobald man ob 2D oder 3D Objekte verwendet und diese Zoomen, drehen ... möchte, arbeitet man am besten mit allgemeinen Vektor, Matrix Operationen, die das alles beinhalten. Für die allgemeine Form dieser Vektor, Matrix Operationen benötigt man für die Berechnung immer eine
zusätzliche virtuelle Dimension. für 2D also (x,y,w), für 3D (x,y,z,w)
Ich gehe jetzt mal nur von moderen Intel/AMD CPUs aus, welche alle MMX/SSE/AVX 256-Bit beherrschen:
hier macht es meiner Ansicht nach wenig Sinn, noch zwischen 2D und 3D Koordinaten zu trennen, da
die SSE/AVX Einheit 4D Koordinaten als single oder double Float in einer Operation berechnen kann.
Meine Überlegung für zukünftige Software:
Immer alles mit gleich mit 4D Double Koordinaten ansetzen, Bei 2D eben z=0
Erwartete Vorteile:
- das sollte mit SSE/AVX sogar schneller sein, als 2D Koordinaten einzeln über die Standardregister zu berechnen
- man hat ein universelles System für 2D und 3D und kann immer die gleichen Funktionen benutzen.
- 2D nach 3D Koordinaten irgendwie transformieren/kopieren entfällt!
- man kann aus 2D Formen direkt 3D-Formen extrudieren, indem man die 2D Form einfach kopiert und mit einer Z-Koordinate versieht.
Damit wäre man wohl schon fast bei einer Mini-CAD-Engine!
(wie man das dann. gezeichnet bekommt ist noch eine offen Frage! Evtl. Umwandlung in Mesh oder vielleicht direkt über irgendwelche OpenGl Funktionen!?)
Nachteil:
- mehr Speicher benötigt (bei den heute üblichen GB Speichern wohl kein echtes Problem)
- so wie ich das bisher sehe, ist davon nichts in PB implementiert. Ausser der Vector4-Typ als single Float. Es ist also wahrscheinlich selber denken und machen angesagt! Das VectorModul für single und double Floats hab ich weitgehend implementiert. Damit kann man aber noch nicht wirklich was anfangen, solange man keine Funktionen für eine allegemeine 2D/3D Objekt-Darstellung und die Umsetzung der Zeichenfunktion hat.
Hat dazu jemand Erfahrung? Liege ich in meiner Einschätzung da richtig? Macht das evtl. schon jemand so?
2D Point vs. 4D Vector Koordinaten
Re: 2D Point vs. 4D Vector Koordinaten
SMaag hat geschrieben: 02.03.2023 13:30 Es geht um die Strategie der Verwendung von 2D Point und 4D Vector-Koordinaten.
Folgende Ausgangspunkte:
- Jup, korrekt.
- Jup, korrekt. Allerdings arbeitet man im 2D Bereich (z.B. SVG oder so) auch gerne mit 3×2-Matrizen und somit auch weiterhin nur mit normalen 2D-Vektoren. Ganz einfach weil Punkte eh immer eine 1 in z haben und normale Transformationsmatrizen auch nix mit dem z machen.
In 3D ist das etwas anders, weil ich dort auch Matrizen für die Projektion nutze, also das mapping von 3D nach 2D. Das gibt es ja nicht im 2D.
Ob man im normalen Graphik-Umfeld wirklich doubles statt float benötigt bezweifle ich.SMaag hat geschrieben: 02.03.2023 13:30 Meine Überlegung für zukünftige Software:
Immer alles mit gleich mit 4D Double Koordinaten ansetzen, Bei 2D eben z=0
Allerdings gebe ich dir recht, dass man generell alles in 4D-Koordinaten machen könnte, wenn man eh schon SSE nutzt.
Ob da nun 2, 3 oder 4 Koordinaten parallel addiert etc. werden ist völlig wurscht.
Worauf willst du hinaus? Das PB keine Vector/Matrix-Mathematik hat ist korrekt. Diese wäre aber auch kaum hilfreich im Zusammenhang mit VectorDrawing, Sprites oder der 3D-Engine, weil bei all diesen Librarys immer mit einzelnen Argumenten x,y,z hantiert wird und man nirgends z.B. einen Vector4-Typ übergeben könnte.SMaag hat geschrieben: 02.03.2023 13:30 - so wie ich das bisher sehe, ist davon nichts in PB implementiert. Ausser der Vector4-Typ als single Float. Es ist also wahrscheinlich selber denken und machen angesagt! Das VectorModul für single und double Floats hab ich weitgehend implementiert. Damit kann man aber noch nicht wirklich was anfangen, solange man keine Funktionen für eine allegemeine 2D/3D Objekt-Darstellung und die Umsetzung der Zeichenfunktion hat.
Hat dazu jemand Erfahrung? Liege ich in meiner Einschätzung da richtig? Macht das evtl. schon jemand so?
Was meinst du mit "allgemeine 2D/3D Objekt-Darstellung"? Meinst du eine 2D/3D-Renderengine?
Zu der Frage "Macht das evtl. schon jemand so?" kann ich sagen: Ja. Ich habe meine Standard-Includes für Vector4f, Matrix4f, Quaternion, usw. alles SSE-optimiert. Diese werden für viele meine Projekte verwendet und wenn ich Richtung Rendering gehe, dann nutze ich die OpenGL Schnittstelle. Dort hab es dann auch Funktionen wie:
UBE_Draw3DVectorLine( *v3fVertex1.UBE_VECTOR3f, *v3fVertex2.UBE_VECTOR3f, lColor.l = $FFFFFFFF )
(das hier über all 3 steht hat nix zu bedeuten, intern war es immer 4)
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Re: 2D Point vs. 4D Vector Koordinaten
Erst mal eine interne Datenstruktur, mit der man Objekte entsprechend speichern kann, so dass man beliebige 2D Formen und 3D Volumenobjekte darstellen kann.Was meinst du mit "allgemeine 2D/3D Objekt-Darstellung"? Meinst du eine 2D/3D-Renderengine?
- 2D Grundformen wie (Dreieck, Viereck, Pentagon, Hexagon, Polygon: Kreis, Ellipse)
- 3D Formen daraus extrudiert als:
Kreis -> Zylinder oder Kegel
Rechteck -> Box oder Pyramide
... usw.!
Dann muss man das noch irgendwie Zeichnen. Wenn man es nicht als Mesh umgewandelt bekommt, dann wahrscheinlich selbst rendern.
Ich kenn ja dein VectorDrawing Beispiel, da ist das so gemacht, dass jeder Punkt einzeln über die CPU gerendert wird.
Meine Momentane Vorstellung wie das geht sind eben die beiden Methoden:
1. Mit der CPU Punkt für Punkt rendern (das dürfte aber bei vielen Objekten recht langsam werden)
2. Die Volumenköper in Mesh umwandeln und dann mit den Meshfunktionen verarbeiten. Ich gehe davon aus, dass dann das ganze Rendering bzw. Pixel oder Voxel Shading auf der Grafikkarte erledigt wird, die dafür hunderte paralleler Einheiten hat.
(Grundunktionen wie CreateCube, CreateTube, CreateTorus.. gibt es in PB ja schon! Damit lassen sich aber nicht alle 3D Formen als Mesh realisieren.
Für mich ist immer noch die Frage, ob man das nicht besser irgendwie der Grafikkarte überlassen kann, da die das eigentlich viel effektiver können müsste als die CPU.
(Mein Endziel: 3D Volumenobjekte auf einer Ebene platzieren und mit der Maus rumschubsen. Die 3D Objekte aus 2D Grundformen extrudieren. Fertige 3D Objekte aus CAD-Systemen wie SolidWorks oder Inventor laden, skalieren und platzieren. Deswegen auch die Beschäftigung mit STL, IGES, und STEP. Falls das mal funktioniern sollte, will ich das evtl. für die Visualisierung von Industrieanlagen verwenden und mit Daten aus der SPS verknüpfen)
Brainstorming Implementierung 3DObj Datenstruktur
hier mal die Brainstorming Implementierung für de 3D-Object Datenstrukturen
Code: Alles auswählen
Structure TVector ; Double precicion Vector [32 Bytes / 256 Bit]
StructureUnion
v.d[0] ; virutal Array v[0]=x, v[1]=y, v[2]=z, v[3]=w
EndStructureUnion
x.d
y.d
z.d
w.d
EndStructure
Structure TMatrix ; Double precicion Matrix
StructureUnion
v.TVector[0] ; Vector interpretation of the Matrix Structure
EndStructureUnion
m11.d : m12.d : m13.d : m14.d
m21.d : m22.d : m23.d : m24.d
m31.d : m32.d : m33.d : m34.d
m41.d : m42.d : m43.d : m44.d
EndStructure
Enumeration eObj3D
; flat objects (2D)
#PbFw_Obj3D_unknown
#PbFw_Obj3D_Text
#PbFw_Obj3D_Line
#PbFw_Obj3D_Polygon
#PbFw_Obj3D_Ellipse
; Volume objects (3D)
#PbFw_Obj3D_3DPolygon
#PbFw_Obj3D_3DCone
EndEnumeration
Enumeration eObj3D_SubType
#PbFw_Obj3D_SubType_unknown
; Subtypes of Text
#PbFw_Obj3D_SubType_TextSingle ; Single Line Text
#PbFw_Obj3D_SubType_TextMulti ; Single Line Text
; SubTypes of Line
#PbFw_Obj3D_SubType_Line ; Line
#PbFw_Obj3D_SubType_PolyLine ; PolyLine
; SubTypes of Ellipse
#PbFw_Obj3D_SubType_Circle ; Circle
#PbFw_Obj3D_SubType_Ellipse ; Ellipse)
; SubTypes of Polygon
#PbFw_Obj3D_SubType_Triangle ; 3 Edges
#PbFw_Obj3D_SubType_Rectangle ; 4 Edges, regualr Rectangel
#PbFw_Obj3D_SubType_Pentagon ; 5 Edges, regular Pentagon
#PbFw_Obj3D_SubType_Hexagon ; 6 Edges, regular Hexagon
#PbFw_Obj3D_SubType_Octagon ; 8 Edges, regular Octagon
#PbFw_Obj3D_SubType_Polygon ; any other Polygon
; SubTypes of 3DPolygon
#PbFw_Obj3D_SubType_3DTriangle ;
#PbFw_Obj3D_SubType_3DBox ;
#PbFw_Obj3D_SubType_3DPentagon ; 5 Edges, regular Pentagon
#PbFw_Obj3D_SubType_3DHexagon ; 6 Edges, regular Hexagon
#PbFw_Obj3D_SubType_3DOctagon ; 8 Edges, regular Octagon
#PbFw_Obj3D_SubType_3DPolygon ; any other Polygon
; SubTypes of 3DCone
#PbFw_Obj3D_SubType_3DCylinder ; 3D Cylinder
#PbFw_Obj3D_SubType_3DEllipticCylinder ; 3D elliptical Cylinder
#PbFw_Obj3D_SubType_3DCone ; 3D Cone {Kegel}
#PbFw_Obj3D_SubType_3DEllipticCone ; 3D elliptical Cone {elliptischer Kegel}
EndEnumeration
Enumeration eObj3D_FillStyle
#PbFw_Obj3D_FillStyle_Transparent = 0 ; Transparent = without filling
#PbFw_Obj3D_FillStyle_Solid ; with solid filling
#PbFw_Obj3D_FillStyle_Pattern ; Musterfüllung (z.B. gestreift)
#PbFw_Obj3D_FillStyle_Image ; Filled with an Image (.bmp, .png, .jpg)
EndEnumeration
Enumeration eObj3D_LineStyle
#PbFw_Obj3D_LineStyle_Solid ; Solid Line : StrokePath()
#PbFw_Obj3D_LineStyle_Dash ; ------ Line : DashPath()
#PbFw_Obj3D_LineStyle_Dot ; ..... Line : DotPath()
#PbFw_Obj3D_LineStyle_DashDot ; -.-.- Line : CustomDashPath()
#PbFw_Obj3D_LineStyle_DashDotDot ; -..-..- Line : CustomDashPath()
EndEnumeration
Structure TLineStyle
Color.l ; Color
Width.d ; Line width
Style.l ; LineStyle {eObj3D_LineStyle}
EndStructure
Structure TFillStyle
Color.l ; Fill Color
GradientColor.l ; Gradient Color {Farbverlauf}
Style.l ; Fill Style {eObj3D_FillStyle}
EndStructure
; ----------------------------------------------------------------------
; Flat Objects -2D
; ----------------------------------------------------------------------
Structure TObjBase
ObjType.i ; Object-Type = #PbFw_Obj3D_Polygon
ObjSubType.i
EndStructure
Structure TObj2DBase Extends TObjBase
LStyle.TLineStyle
NoOfPts.i ; Number of Points = 2
Array PT.TVector(0) ; Array of Points. Point(0) = Reference Point; Object defintion Points start at PT(1)
EndStructure
Structure TLine Extends TObj2DBase
; Line defintion is excatly the TObj2DBase Structure
EndStructure
Structure TPolygon Extends TObj2DBase
Fill.TFillStyle
EndStructure
Structure TEllipse Extends TObj2DBase
Fill.TFillStyle
Rx.TVector ; Radius X
Ry.TVector ; Radius Y
EndStructure
; ----------------------------------------------------------------------
; Volume Objects
; ----------------------------------------------------------------------
Structure TObj3DBase Extends TObjBase
RefPt.TVector ; Reference Point
TMx.TMatrix ; Object's Transformation Matrix
EndStructure
Structure T3DPolygon Extends TObj3DBase ; volume Quadrangle
POL.TPolygon[2]
EndStructure
Structure T3DCone Extends TObj3DBase ; volume Circle (Cylinder, Cone)
EL.TEllipse[2]
EndStructure
Procedure.i Create_Circle(*Obj3D.TEllipse, r.d)
; ============================================================================
; NAME: Create_Circle
; DESC: Create a Circle definition in a TEllipse Structure
; DESC: with Center Point = [0,0,0]
; VAR(*Obj3D.TEllipse) : Pointer to the Polygon Object
; VAR(r.d): Radius
; RET.i : *Obj3D
; ============================================================================
With *Obj3D
\ObjType = #PbFw_Obj3D_Ellipse
\ObjSubType = #PbFw_Obj3D_SubType_Circle
EndWith
With *Obj3D\PT(1)
\x = 0
\y = 0
\z = 0
EndWith
With *Obj3D\Rx
\x = r
\y = 0
\z = 0
EndWith
With *Obj3D\Ry
\x = 0
\y = r
\z = 0
EndWith
ProcedureReturn *Obj3D
EndProcedure
Procedure.i Create_Ellipse(*Obj3D.TEllipse, rx.d, ry.d)
; ============================================================================
; NAME: Create_Ellipse
; DESC: Create an Ellipse definition in a TEllipse Structure
; DESC: with Center Point = [0,0,0]
; VAR(*Obj3D.TEllipse) : Pointer to the Polygon Object
; VAR(r.d): Radius
; RET.i : *Obj3D
; ============================================================================
With *Obj3D
\ObjType = #PbFw_Obj3D_Ellipse
\ObjSubType = #PbFw_Obj3D_SubType_Ellipse
EndWith
With *Obj3D\PT(1)
\x = 0
\y = 0
\z = 0
EndWith
With *Obj3D\Rx
\x = rx
\y = 0
\z = 0
EndWith
With *Obj3D\Ry
\x = 0
\y = ry
\z = 0
EndWith
ProcedureReturn *Obj3D
EndProcedure
Procedure.i Create_Rectangle(*Obj3D.TPolygon, width.d, height.d)
; ============================================================================
; NAME: Create_Rectangle
; DESC: Create a Rectangle definition in a TPolygon Structure
; VAR(*Obj3D.TPolygon) : Pointer to the Polygon Object
; VAR( width.d) : Width
; VAR( height.d) : Height
; RET.i : *Obj3D
; ============================================================================
; P1--------------P2
; | |
; | |
; | |
; P0--------------P3
With *Obj3D
\NoOfPts = 4
If ArraySize(*\PTs()) <> \NoOfPts
ReDim \PTs(\NoOfPts)
EndIf
\ObjType = #PbFw_Obj3D_Polygon
\ObjSubType = #PbFw_Obj3D_SubType_Rectangle
EndWith
With *Obj3D\PT(1)
\x = 0
\y = 0
\z = 0
EndWith
With *Obj3D\PT(2)
\X = 0
\Y = height
\Z = 0
EndWith
With *Obj3D\PT(3)
\X = width
\Y = height
\Z = 0
EndWith
With *Obj3D\PT(4)
\X = width
\Y = 0
\Z = 0
EndWith
*Obj3D\PT(0) = *Obj3D\PT(1) ; Set Reference Point PT(0)
ProcedureReturn *Obj3D
EndProcedure
Procedure.i Create_3DBox(*Obj3D.T3DPolygon, X.d, Y.d, width.d, height.d, depth.d)
; ============================================================================
; NAME: Create_3DBox
; DESC: Create a 3D Box definition in a T3DPolygon Structure
; DESC: with Reference Point = [0,0,0]
; VAR(*Obj3D.T3DPolygon) : Pointer to the 3DPolygon Object
; VAR(width.d): width (lenth in x-direction)
; VAR(height.d): height (lenth in y-direction)
; VAR(depth.d): depth (lenth in z-direction)
; RET.i : *Obj3D
; ============================================================================
; .p5------------.p6
; . | . |
; P1--------------P2 |
; | | | |
; | .p4---------|--.p7
; | . |.
; P0--------------P3
DBG::mac_CheckPointer(*Obj3D) ; Check Pointer Exception
With *Obj3D
\ObjType = #PbFw_Obj3D_3DPolygon
\ObjSubType = #PbFw_Obj3D_SubType_3DBox
Create_Rectangle(\POL[0], width, height)
\POL[1] = \POL[0]
EndWith
With *Obj3D\POL[1]
\PT(1)\z = depth
\PT(2)\z = depth
\PT(3)\z = depth
\PT(4)\z = depth
EndWith
With *Obj3D\RefPt
\x=0
\y=0
\z=0
\w=0
EndWith
ProcedureReturn *Obj3D
EndProcedure
Re: 2D Point vs. 4D Vector Koordinaten
Hier musst du dir aber schon zu beginn überlegen, wie die Formen (2D/3D) überhaupt gespeichert werden sollen.SMaag hat geschrieben: 02.03.2023 18:57Erst mal eine interne Datenstruktur, mit der man Objekte entsprechend speichern kann, so dass man beliebige 2D Formen und 3D Volumenobjekte darstellen kann.Was meinst du mit "allgemeine 2D/3D Objekt-Darstellung"? Meinst du eine 2D/3D-Renderengine?
- 2D Grundformen wie (Dreieck, Viereck, Pentagon, Hexagon, Polygon: Kreis, Ellipse)
- 3D Formen daraus extrudiert als:
Kreis -> Zylinder oder Kegel
Rechteck -> Box oder Pyramide
... usw.!
Im 2D-Bereich kannst du z.B. entweder wie du jetzt alle "Sonderformen" (Vieleck, Eliipsen, etc.) als extra Type mit eigener Struktur speichern. Oder aber, du hast nur eine einzige Form, nämlich Bézierkurven oder Splines, mit denen du ja alles Darstellen kannst aber dann nur noch ein einziges Speicherformat/Rendertool brauchst.
Im 3D-Bereich kannst du auch wieder überlegen ob du wieder alle möglichen Formen als extra Datenstruktur speicherst oder zu einem allgemeinen Format gehst: Mesh oder Voxel.
Das Zeichnen/Rendern solltest du definitiv der Grafikkarte überlassen. Mein Drawing3D war ja auch ausdrücklich nur für "kleine Spielereien" und keine 3D-Renderengine.
Zu deinem Brainstorming:
- Deinen 2D-Objekten fehlt die Transformationsmatrix. Denn auch 2D-Objekte können ja gedreht, geschert oder gezoomt werden.
- Mir ist nicht ganz klar, warum du die beiden Radien einer Ellipse in zwei Vektoren speicherst, statt in X und Y eines Vektors.
- Deinen "Reference Point" brauchst du m.M. nach nicht, da du ja eine Transformation Matrix hast, in der die Translation oder aber der Bezugspunkt drin steht.
____________________
Ganz allgemein würde ich dir dann noch zu folgender Struktur raten (falls ich es richtig Verstanden habe was du vorhast):
Du solltest zwischen Objekten und Shapes unterscheiden: Shapes enthalten z.B. nur Informationen zur Form selber, aber keine Transformation oder Styles. Objekte referenzieren dann zu diesen Shapes und enthalten dann die Transformationsmatrix und Infos zu Farben und Design. Das gilt sowohl für 2D als auch für 3D.
So ist das Implementieren von Shape-Instanzen und Objekt-Instanzen und Boolean-Operationen auch einfacher.
Wenn du z.B. lauter Zylinderlöcher aus einer Box subtrahieren willst (Lochgitter), dann brauchen die einzelnen Zylinder keine Info über Farbe oder Höhe und Radius, du brauchst nicht mal mehrere Zylinder. Es wäre nur ein Shape (Einheits-Zylinder) mit einem Array von Transformationsmatrizen (Ort, Höhe, Radius) nötig und das Objekt selbst enthält erst Boolean-Operation der Shapes (Zylinderinstanzen und Box) und die Farbe.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Re: 2D Point vs. 4D Vector Koordinaten
@STARGATE
Danke! Das liefert mir ein paar nötige Impulse!
Aber nochmals zur Grafikkarte:
Die einzige Methode ist wohl, alles in Meshes zu konvertieren! Oder gibt es noch andere Methoden?
Danke! Das liefert mir ein paar nötige Impulse!
Aber nochmals zur Grafikkarte:
Die einzige Methode ist wohl, alles in Meshes zu konvertieren! Oder gibt es noch andere Methoden?