2D Point vs. 4D Vector Koordinaten

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
SMaag
Beiträge: 184
Registriert: 08.05.2022 12:58

2D Point vs. 4D Vector Koordinaten

Beitrag von SMaag »

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?
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: 2D Point vs. 4D Vector Koordinaten

Beitrag von STARGÅTE »

SMaag hat geschrieben: 02.03.2023 13:30 Es geht um die Strategie der Verwendung von 2D Point und 4D Vector-Koordinaten.

Folgende Ausgangspunkte:
  1. Jup, korrekt.
  2. 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.
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
Ob man im normalen Graphik-Umfeld wirklich doubles statt float benötigt bezweifle ich.
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.
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?
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.
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
SMaag
Beiträge: 184
Registriert: 08.05.2022 12:58

Re: 2D Point vs. 4D Vector Koordinaten

Beitrag von SMaag »

Was meinst du mit "allgemeine 2D/3D Objekt-Darstellung"? Meinst du eine 2D/3D-Renderengine?
Erst mal eine interne Datenstruktur, mit der man Objekte entsprechend speichern kann, so dass man beliebige 2D Formen und 3D Volumenobjekte darstellen kann.
- 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)
SMaag
Beiträge: 184
Registriert: 08.05.2022 12:58

Brainstorming Implementierung 3DObj Datenstruktur

Beitrag von SMaag »

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


Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: 2D Point vs. 4D Vector Koordinaten

Beitrag von STARGÅTE »

SMaag hat geschrieben: 02.03.2023 18:57
Was meinst du mit "allgemeine 2D/3D Objekt-Darstellung"? Meinst du eine 2D/3D-Renderengine?
Erst mal eine interne Datenstruktur, mit der man Objekte entsprechend speichern kann, so dass man beliebige 2D Formen und 3D Volumenobjekte darstellen kann.
- 2D Grundformen wie (Dreieck, Viereck, Pentagon, Hexagon, Polygon: Kreis, Ellipse)
- 3D Formen daraus extrudiert als:
Kreis -> Zylinder oder Kegel
Rechteck -> Box oder Pyramide
... usw.!
Hier musst du dir aber schon zu beginn überlegen, wie die Formen (2D/3D) überhaupt gespeichert werden sollen.
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
SMaag
Beiträge: 184
Registriert: 08.05.2022 12:58

Re: 2D Point vs. 4D Vector Koordinaten

Beitrag von SMaag »

@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?
Antworten