Vectoren, Matrix und vieles mehr

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
GPI
Beiträge: 1510
Registriert: 29.08.2004 13:18
Kontaktdaten:

Vectoren, Matrix und vieles mehr

Beitrag von GPI »

Wenn man sich mit 3D-Grafiken auseinandersetzt, wird man früher oder später das Problem bekommen, das man Berechnungen mit Matrixen und Vectoren durchführen muss.

Für C++ gibts schöne Bibliotheken, GLM zum Beispiel. Und genau diese hab ich jetzt zum großen Teil für PB übersetzt:
https://github.com/GPIforGit/math/releases/

Es gibt zwei Möglichkeiten, die Sammlung zu nutzen:

1) Einfach das Verzeichnis in dein Projekt kopieren und so einbinden:

Code: Alles auswählen

XIncludeFile "math/math.pbi"
2) das Install-Script benutzen, es erstellt einen "include"-Ordner in Pure-Basic-Verzeichnis und kopiert sich dann da rein. Damit muss man nicht mehr für jedes Projekt den Math-Ordner kopieren:

Code: Alles auswählen

XIncludeFile #PB_Compiler_Home + "Include/math/math.pbi"
ACHTUNG: Bitte nicht "UseModule Math" benutzen, außer man steht auf Probleme.

Es gibt 4 Vektoren
  • math::vec2
  • math::vec3
  • math::vec4

ein Quaternion
  • math::quat


und viele Matrixen:
  • math::mat2x2
  • math::mat2x3
  • math::mat2x4
  • math::mat3x2
  • math::mat3x3
  • math::mat3x4
  • math::mat4x2
  • math::mat4x3
  • math::mat4x4
Die meisten Proceduren/Macros verlangen als ersten Parameter ein "Return"-Value. PB kann ja keine Struckturen zurückgeben.
einfaches Beispiel:

Code: Alles auswählen

	Define.math::vec3 v1,v2,vres
	math::vec3_set(v1, 1,2,3)
	math::vec3_set(v2, 2,4,5)

	math::vec3_add(vres, v1,v2)

	Debug math::string(vres)
Es gibt auch einige "dispatcher" Macros, die je nach parametertyp (Vector, Matrix, etc.) die richtige Procedure auswählt. Das gleiche Beispiel könnte man auch so schreiben:

Code: Alles auswählen

	Define.math::vec3 v1,v2,vres
	math::set_float(v1, 1,2,3)
	math::set_float(v2, 2,4,5)

	math::add(vres, v1,v2)

	Debug math::string(vres)
ein Beispiel mit Matrix:

Code: Alles auswählen

	Define.math::vec3 v
	Define.math::vec3 vres
	Define.math::mat3x3 m

	math::set_float(m, 1) ; createas a identity matrix

	math::set_float(v,2) ; set all values of the vector to 2

	math::mul(vres, m, v) ; equals vres = m4*v

	Debug math::string(vres) + " = " + math::string(m) + " * " + math::string(v)
oder "ausgeschrieben":

Code: Alles auswählen

	Define.math::vec3 v
	Define.math::vec3 vres
	Define.math::mat3x3 m

	math::Mat3x3_set_Scalar(m, 1) ; createas a identity matrix

	math::vec3_set_Scalar(v,2) ; set all values of the vector to 2

	math::Mat3x3_mul_Vec3(vres, m, v) ; equals vres = m4*v

	Debug math::string(vres) + " = " + math::string(m) + " * " + math::string(v)

Es gibt eine menge an Proceduren, dot, length, cross usw.
res in math:: - for example dot, length, cross and so on.
In der "test.pb" gibt es weitere Beispiele.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6825
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Vectoren, Matrix und vieles mehr

Beitrag von STARGÅTE »

Hab es gerade im englischen Forum schon gesehen und mal durchgeschaut.
Sehr großes und vollständiges include und auch auf viele "Details" geachtet z.B. das Clamp bevor du ASin() machst bei den quatemion, ich hoffe für die ganzen Matrixvarianten hast du dir n Script geschrieben was den Code generiert und nicht alles per Hand geschrieben.
Allerdings bin ich überhaupt kein Fan von Macros ;-), weil es den Umgang mit Pointern (ohne Struktur) echt erschwert.
Da ich selbst auch schon n 3D-Engine geschrieben habe, habe ich so ein Include bereits. Ich behandle die 4er Vektoren etwas anders als du das machst. Bei dir wird auch die w-Koordinate wie die 3 Raumachsen behandelt, obwohl sie ja eine ganz eigene Bedeutung hat und eigentlich immer nur 0 (Richtung) oder 1 (Ort) ist. Ist das absicht?
Gerade weil du ja schreibst, dass man es für OpenGL nutzen kann, wäre es sehr nervig, wenn die w-Koordinate irgendein "Blödsinn" macht.
Beispiel: Wenn ich ein Mesh mit Vertices (x, y, z, 1) skaliere, dann sollte die w-Koordinate eigentlich nicht mit skaliert werden, sondern immer 1 bleiben.

Eine Detailfrage / Idee: Bei deinen Min und Max Funktionen könntest du statt der NaN abfrage, doch im Prozedurargument gleich selbst Unendlich oder -Unendlich angeben:

Code: Alles auswählen

#Infinity = 1e400
Procedure.d Min(A.d=#Infinity, B.d=#Infinity, C.d=#Infinity)
PB 5.73 ― Win 10, 20H2 ― Ryzen 9 3900X ― Radeon RX 5600 XT ITX ― Vivaldi 3.6 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
GPI
Beiträge: 1510
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Vectoren, Matrix und vieles mehr

Beitrag von GPI »

Das mit der w-Achse ist eigentlich so, das ich es (wenn ich keinen Blödsinn mache) exakt wie glm ( https://github.com/g-truc/glm ) das ist auch die Basis der ganzen Datei. Und die Orientiert sich an OpenGL. Ich übersetze gerade die ganzen http://www.opengl-tutorial.org - bin gerade bei Tutorial17 Drehungen (und hab festgestellt, das mir noch die euler_angle-Varianten dafür fehlen - nochmals ein paar Hundert C-Zeilen...)

Skaliert wird übrigens bei opengl-tutorial anders - durch eine skalierungs-matrix.
Aktuell würde ich versuchen über die "MVP" ( mvp = ProjectionMatrix * ViewMatrix * ModelMatrix) zu machen, genauer die Modelmatrix.
Mit der MVP muss der Shader eh alles multiplizieren, von daher kostet es mich eigentlich nichts weiter extra, ein komplettes Modell zu skalieren.

das mit den NAN bei min ist "einfach":
Wenn du min(10,nan()) übergibts, soll 10 rauskommen. Wenn du aber min(nan(),nan()) übergibst, soll immer nan() rauskommen.
Ich will halt nan() mit nichts vergleichen, weil ich keine Ahnung hab, ob da was definiert wurde oder reiner Zufall ist, ob was rauskommt. Deshalb wandle ich es vor den vergleich nach in infinity() um. Wenn ich als default-Paramater infitiy nehme, dann könnte ich nicht mehr rausfinden, ob bspw. nur 2 parameter übergeben wurde und eigentlich nan() rauskommen soll...

Übrigends die ganze Datei arbeitet mit Float. Auch deshalb, weil sämtliche Beispiele die ich mit OpenGL gefunden hab, immer Floats sind.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
GPI
Beiträge: 1510
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Vectoren, Matrix und vieles mehr

Beitrag von GPI »

Auch hier gibts ein Update:
https://github.com/GPIforGit/math/releases

; - add rotate_float, translate_float, scale_float - replace the vector with floats
; - replaced many macros with procedures and all procedures returns now the res-pointer. this allows nested calls
; like vec3_mul(res, vec3_add(a, b,c), a) equals "a=b+c: res=aa" equals "res = (b+c)(b+c)"
; - add many vec2_, vec3_, vec4_ for dot, length, normalize and so on
; - add this comment
; - add "euler_angles" from glm
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Antworten