Deutsch
PHP, HTML & JavaScript- Forum

3D Grafik - WebGL mit three.js

 
- Seite 1 -



HofK
Auf einen heißen Tipp von IF hin, habe ich mir mal
three.js  [...]  angeschaut. Da  [...]  (ganz unten) die ersten Resultate.
 
31.01.2016  
 



 
- Seite 4 -



HofK
Ungültig:

HofK (25.03.2017)
ACHTUNG! Nicht zu lange laufen lassen, das Speicherleck ist noch aktiv. Es sei denn, man möchte mal testen wie es ist, wenn der Browser in die Knie geht.



Speicherleck soeben gestopft!
Demnächst mehr dazu.

Wer seinen Browser lahm legen möchte braucht ein anderes Objekt.
 
01.04.2017  
 




HofK
Das Speicherleck.

Im Manual von three.js  [...]  gibt es den Punkt "How to update things" und dort zur Geometrie eine Auflistung. Aus Beispielen und durch Versuche hatte ich herausgefunden, dass geometry.elementsNeedUpdate = true; es ermöglicht, den Materialindex zu ändern und damit ein Multimaterial aus verschiedenen Einzelmaterialien dynamisch zu nutzen.

Funktioniert ja auch prima. Nur dann eben das Speicherleck !

Nachdem auf meine etwas umfangreichere Frage bei stackoverflow   [...]  keine Antwort kam, habe ich nach Experimenten eine ähnlich gelagerte aber doch andere und sehr knappe Frage gestellt:  [...] 

Sie wurde sehr schnell von WestLangley (Mitautor von three.js) beantwortet und führte mich nach Umwegen auf die richtige Spur. In der Antwort auf das einfache Problem reicht geometry.colorsNeedUpdate = true;, aber das hilft nicht beim Multimaterial.

Somit habe ich alle möglichen Dinge durchsucht. Im recht nett anzusehendenBeispiel  [...]  findet man dann elementsNeedUpdate um die Eckpunkte der Faces (Dreiecke) dynamisch zu ändern und den nicht bei "How to update things" aufgeführten Befehl groupsNeedUpdate um den Materialindex zu manipulieren. Also ein nicht dokumentierter Befehl, der aber wohl ausreicht. Der Befehl kam sicher erst später hinzu, three.js entwickelt sich noch sehr dynamisch.

Nachdem ich den langsamen Takt des Beispiels von 1000ms auf 10ms drastisch verändert hatte, ergab es ein Speicherleck. Aber nur bei elementsNeedUpdate!

Im Quelltext von three.js findet man dann die Passage:

if ( material && material.isMultiMaterial ) {

var groups = geometry.groups;
var materials = material.materials;

for ( var k = 0, kl = groups.length; k < kl; k ++ ) {

var group = groups[ k ];
var groupMaterial = materials[ group.materialIndex ];
...


Sie zeigt, dass der Materialindex in Gruppen organisiert ist.

Somit ist die Lösung meines Problems der Austausch eines einzigen Befehls. Habe nun meine Frage bei stackoverflow   selbst beantwortet.

Wenn ich aber vorhaben sollte auch die Eckpunkte der Dreiecke dynamisch zu wechseln, gibt es das Leck.

Ich glaube, dass dies intern in Javascript/three.js so komplex ist, dass ab einer bestimmten Flächenanzahl und einem Takt es nicht mehr möglich ist, dass die Garbage Collection hinterherkommt.

Dann muss man wahrscheinlich auf die Shader umsteigen, die ich in Minibeispielen getestet habe.  [...] 
 
03.04.2017  
 




HofK
Habe noch ein wenig den Code optimiert und dann einige weitere Beispiele für die Formen-Bibliothek gebastelt.

Dabei bin ich auf eine interessante Seite zu dekorativen Knotenmustern
gestoßen.  [...] 

Die dort angegebenen Formeln lassen sich mit entsprechender Anpassung unmittelbar übernehmen. Das Beispiel
heightSegments:	400,
centerX:	function ( v, t ) { return Math.cos( 4*v *2*Math.PI ) * ( 1 + 0.5 * ( Math.cos( 5*v *2*Math.PI ) + 0.4 * Math.cos( 20*v *2*Math.PI ))) },
centerY:	function ( v, t ) { return Math.sin( 4*v *2*Math.PI ) * ( 1 + 0.5 * ( Math.cos( 5*v *2*Math.PI ) + 0.4 * Math.cos( 20*v *2*Math.PI ))) },
centerZ:	function ( v, t ) { return 0.35 * Math.sin( 15*v *2*Math.PI ) }



habe ich in die Bibliothek  [...]  aufgenommen und dort den Link zu den Mustern vermerkt.
 
07.04.2017  
 




HofK
Bei den bisherigen Beispielen habe ich fast immer die Textur uv Grid benutzt, um die Formen besonders deutlich zu machen.

Als ich nun einige nur einfarbige Gebilde erzeugt habe, ist mir aufgefallen, dass in der Sandbox die 3D Form nicht wirklich gut sichtbar wird. Deshalb habe ich am Licht "geschraubt" und THREE.FlatShading bei den Materialien definiert. Damit wird die Gitterstruktur sichtbar. Das Beispiel // eight-part von  [...]  sieht dann z.B. so aus

 
14.04.2017  
 




HofK
THREE.FlatShading ist für die Konstruktion zwar recht praktisch, aber richtig schön glatte Oberflächen sehen viel netter aus.

Deshalb habe ich nun in den Sandkasten beim Material eine Checkbox flat shading eingefügt. Mit ihr kann man dann nach Bedarf vom Standard smooth shading zu flat shading wechseln.

 [...] 
 
15.04.2017  
 




HofK
Die 3D Konstruktion mit THREE.js und Funktionen ermöglicht eine schier unendliche Vielzahl von Formen. Auch die Bewegungen und Änderungen der Gestalt sind fast unerschöpflich.

Eine Schwierigkeit ist allerdings die richtigen Funktionen zu finden. Manchmal ist das entweder unmöglich oder viel zu kompliziert. Stellt man sich eine bestimmte Mittelpunktskurve vor, so ist es eventuell zu aufwändig oder unmöglich drei passende Funktionen centerX(), centerY(), centerZ() zu ermitteln.

Aus diesem Grund habe ich die Möglichkeit geschaffen, statt der drei Funktionen ein Datenfeld von Koordinatenpunkten anzugeben. Dabei sind normalerweise Werte zwischen 0 und 1 anzugeben, so wie das für die Argumente und Funktionswerte der Funktionen gilt. Die Skalierung erfolgt dann wieder über radius und height.

Intern werden die Funktionswerte nur durch die Werte im Datenfeld ersetzt und aus dem räumlichen Abstand der Punkte werden die Werte für die Höhenskalierung berechnet. Die Anzahl der Höhensegmente ergibt sich aus der Anzahl der angegebenen Punkte minus 1.

Um das Datenfeld zu aktivieren, muss die Checkbox markiert werden. Das Datenfeld kann unmittelbar eingetippt bzw. manipulieren werden, oder man kopiert es aus Vorlagen. Man kann die Geometrie laufend mit dem Button "apply now / show mesh" begutachten. So kann man die Koordinaten in der Sandbox testen und wenn es gefällt das Datenfeld für die Definition einer Geometrie wie in den Beispielen kopieren. Bei der Javascript Definition wird geprüft, ob ein Datenfeld centerPoints als Parameter angegeben ist. Wenn ja und es nicht das leere Datenfeld ist, wird es benutzt, ansonsten die center - Funktionen. Sind diese nicht angegeben, greifen die default -Funktionen.



Schließt man das Eingabefenster, ist auf dem Button vermerkt, ob das Datenfeld benutzt wird.

Die Funktion ist schon ein paar Tage online, sollte jetzt aber vollständig sein.  [...]  Dort ist das Beispiel:  [...]  [...] 
 
18.04.2017  
 




HofK
Damit die hübschen Funktionen-Gebilde nicht nur hier von einer kleinen Schar Interessierter angesehen werden können, habe ich auf codepen  [...]  eine Variante der Beispiele samt Bibliothek eingestellt.

Dort oben rechts die Suche (Lupe) anklicken und three.js eintippen und abentern. Man bekommt über 4000 Einträge in der Rubrik Pens!
Deshalb momentan dann einfach "Order results by"  Newest first wählen und es findet sich noch ziemlich am Anfang.

Demnächst ist dann ein anderer Suchbegriff nötig um es zu finden: hofk

Die Suche bei codepen ist nicht wirklich überzeugend und bei den unzähligen Beiträgen findet man dann nicht wirklich was man sucht. Deshalb habe ich einen der fünf möglichen Tags einfach auf mein Kürzel gesetzt. Die vier anderen Tags sind three.js, multimaterial, geometry, motion.



Einfach mal schauen, was es da sonst noch so gibt.
 
22.04.2017  
 




HofK
Nachdem mir ein deutschsprachiger Mitautor von three.js bestätigt hat, was ich auch nach meinen Recherchen vermuten musste, Zitat:

"... Außerdem sind so gut wie alle relevanten Bücher, Blog-Posts, Dokumentationen oder wissenschaftliche Paper im Kontext der webbasierten 3D-Grafikprogrammierung und three.js auf Englisch. In deutscher Sprache wirst du so gut wie nichts finden. Aber keine Sorge. Du musst Englisch keinesfalls fließend können. ... " 

habe ich mich daran gemacht und das Projekt ordentlich wie auch three.js bei GitHub eingestellt.  [...] 

Naja, Englisch kann ich ja nun wirklich nicht fließend!
Aber mit etwas Routine gelingt es mit Hilfe von Google Übersetzer die Sachen immer zeiteffektiver und etwas weniger stressig hinzubekommen. Man muss nur den "Übersetzungsmüll" aussortieren, der gerade bei Wortgruppen / Sätzen mit Fachbegriffen oft herauskommt. Übungssache und man lernt dann nebenbei.

Habe dann das Projekt auch im recht neuen offiziellen three.js Forum in der Kategorie Resources vorgestellt:  [...]  unter forum oder direkt [...]  .

Bevor ich die Sache online gebracht habe, musste ich beim Test ob mein addon auch unter der brandneuen Revision 85 von three.js läuft feststellen, dass eine Änderung beim Material vorgenommen wurde.

Statt ein gesondertes MultiMaterial  zu definieren, braucht man jetzt nur noch das array  der Materialien anzugeben. So konnte ich in GitHub gleich üben, wie man solche Updates einspielt.

Oben erwähnter Mitautor hat mir indirekt auch noch gleich eine Aufgabe mitgegeben:

"Noch ein kleiner Tipp: THREE.Geometry solltest du zur Generierung von Geometrien nicht mehr verwenden. THREE.BufferGeometry allokiert viel weniger Ressourcen und ist deutlich performanter. Außerdem konvertiert die interne Render-Logik von three.js THREE.Geometry automatisch nach THREE.BufferGeometry." 

Dazu muss man wissen, dass THREE.BufferGeometry schwieriger zu handhaben ist und in der Dokumentation stand, dass es sich für statische Dinge besonders eignet. Aber das ist wohl nicht so relevant, es gibt static oder dynamic.

.dynamic
Whether the buffer is dynamic or not. Default is false.
If false, the GPU is informed that contents of the buffer are likely to be used often and not change often. This corresponds to the gl.STATIC_DRAW flag.
if true, the GPU is informed that contents of the buffer are likely to be used often and change often. This corresponds to the gl.DYNAMIC_DRAW flag.


Das geht in die shader Programmierung - siehe Beispiel weiter oben.

Dann werde ich jetzt mal ----- und mir BufferGeometry  [...]  vorknöpfen.
 
27.04.2017  
 




HofK
Der Anfang ist gemacht, wenn das klappt ist die Stimmung gut und es kann (fast) nichts mehr schief gehen.

Aus dem nicht vollständig anfängerfreundlichen, aber überaus tollem Beispiel mit viel Bewegung, Live und mit Code zu betrachten und bei Bedarf auch manipulierbar  [...] 



habe ich ein total primitives Beispiel zusammengestrichen. Das kann jeder durchschauen.



Bei THREE.BufferGeometry() werden die Daten in Datenfeld-Puffern gehalten, damit entfällt die Strukturierung und man muss sich selber um die Indizes kümmern. Da habe ich Glück, das ist eh' mein Ding, ich liebe Indexrechnungen.

var triangles = 2;
var positions = new Float32Array( triangles * 3 * 3 ); // buffer arrray, position of vertices
var colors = new Float32Array( triangles * 3 * 3 );// buffer arrray, vertexColors

Zum Anfang habe ich aber selbst die Schleife rausgeschmissen und fixe Indizes angegeben, das macht es noch transparenter.

Die "Spezialität" bei den Buffern sind die Attribute:

geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );


Und da kann man das primitive Beispiel und per Strg+U den Quellcode betrachten:  [...] 

--------------------------------------

UPDATE - Noch etwas Farbe hinzugefügt und ein Quadrat mit einer Textur.



Nachtrag: Siehe jetzt auch zwei Varianten auf
 [...]  .
 
27.04.2017  
 




HofK
Den folgenden Text - aber in Englisch - habe ich auf discourse.threejs.org  [...]  eingestellt:

Editierbare Formen Bibliothek auf GitHub

Mit Hilfe der Funktionen lassen sich mit THREEf.js sehr vielfältige Formen erzeugen. Es ist aber nicht immer einfach, zu einer Figur die man sich vorstellt, die passenden Formeln zu finden.

Deshalb habe ich die Bibliothek von PDF auf HTML umgestellt. Sie ist auf GitHub verfügbar. So kann man seine Formen dort anderen Nutzern zur Verfügung stellen.

Durch eine große Bibliothek wird THREEf.js dann für viele Nutzer einfach anwendbar.

Gestalte eine Geometrie und füge sie der Bibliothek an: [...] 

Eine Kurzanleitung befindet sich am Ende der Datei:
document.images[0...].src = "img/    .png";
parameterList[0...].value = "//0...Here is the right place for your example! \n ";
//__________________________________________________________

// +++++ Do not destroy the following instructions. +++++
//
// Copy the last section, increase the indices and then describe your form in the penultimate section.
// Set the number nnnn, a description and your author tag, possibly with URL.
// If you copy the list of parameters into the string, replace the line break with \n
// Copy your image to the img directory and use the pattern from above (fourDigits_name.type) for the name.
// Take png (or jpg) images up to approximately 100KByte.
//
// If the image is not square, change the height or width in your section:
// document.images [index].width = "value" or document.images [index].height = "value"
// See examples index 3 and 10, standard is 160 x 160.
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
</script>

Ich bin neu bei GitHub, ich hoffe, es funktioniert.


Wer einmal ausprobieren möchte, wie man bei GitHub einen Beitrag zu einem Projekt leistet, kann das hier gefahrlos machen.

Einfach einen Account bei GitHub erstellen und auf den Speicherort THREEf gehen. Da der öffentlich ist, entstehen auch mir keine Kosten. Nur für private Nutzung muss man zahlen.



Jetzt den Menüpunkt Pull requests anwählen und dann
den grünen Button New pull request betätigen.

Alle Änderungen die man macht, werden in den Zweig dev(elopment) geschrieben und die Beiträge werden tranparent dokumentiert.

Nach einer Zeit muss ich mir die Änderungen anschauen und "genehmigen". Erst dann werden sie von mir in den geschützen Zweig master übernommen.

Probieren konnte ich das so noch nicht, da ich keinen Pseudoaccount erzeugen möchte.

Also keine Scheu und probieren, es kann nichts kaputt gehen, im Notfall hier per Private Nachricht oder per Mail mit mir in Kontakt treten.
 
02.05.2017  
 




HofK
Schaut man genauer nach der BufferGeometrie, so entdeckt man zwei Varianten, indiziert und nicht indiziert.

Bei der nicht indizierten Variante ist die Geometrie eine "Dreieckssuppe", die Koordinaten aller Eckpunkte aller Dreiecke werden nacheinander angegeben. Klingt erst einmal einleuchtend, ist es auch, wenn alle Dreiecke wie in einer Suppe die Nudeln frei herumschwimmen.

Bei "ordentlichen" Körpern oder flächigen Gebilden sind die Dreiecke aber aneinander geheftet. Trotzdem muss man die identischen Ecken immer wieder für jedes Dreieck speichern. Bei meinem THREEf sind es bis zu sechs und bei einem Zentralpunkt (waffled) bis zu acht mal!

Die indizierte Variante verhält sich so wie die "normale" THREE.Geometry. Man gibt alle Punkte nur einmal an. Dazu dann ein weiteres Datenfeld der Indizes. Hier werden für jedes Dreieck die Indizes der jeweils drei Eckpunkte gespeichert.
var geometry = new THREE.BufferGeometry();

var positions = new Float32Array( 4 * 3 ); // buffer arrray, position of 4 vertices
var indices = new Uint32Array( 2 * 3 ); // indices for 2 faces
var colors = new Float32Array( 4 * 3 ); // buffer arrray, 4 vertexColors * 3 color channels


// 2 faces with 3 vertices indices

// face 0: vertices indices 0, 1, 2
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;

// face 1 vertices indices 0, 1, 3
indices[3] = 0;
indices[4] = 1;
indices[5] = 3;

Diese Variante werde ich benutzen. Sonst müsste ich eine Systematik von Grund auf neu erstellen. Bei der indizierten Variante kann ich diese in den Code einmischen und muss nur die Zugriffe auf die Datenfelder und einige andere Sachen extra behandeln. Dazu frage ich ab, ob eine Geometry oder BufferGeometry vorliegt. Dies ist eine verfügbare interne Eigenschaft.

Damit das nun mit "Buffer" auch zügig klappt, habe ich zur Übung erst einmal zwei Anfängerbeispiele zum Vergleich der Varianten gebastelt:  [...] 
 
03.05.2017  
 




HofK
Wie erwartet, hat das mit der Angabe der Punkte und der Indizes für die einzelnen Dreiecke recht reibungslos geklappt und ein Gitternetz war über die BufferGeometry schon recht schnell in der Sandbox und den Beispielen verfügbar.

Dann kam der erste "Dämpfer". Was ich noch nicht bemerkt hatte?
Bei Geometry wird das uv-Mapping über die Dreiecke gesteuert, man muss für jede Ecke die Koordinaten angeben.

Bei BufferGeometry werden die uv-Koordinaten aber direkt bei den Vertices (Knoten) angegeben. Da musste ich schon jonglieren, um das einzumischen. Hat soweit geklappt, aber es bleibt ein Problem: Wenn nicht "circular open" , also verbunden, werden die letzten Dreiecke gebildet, indem sie an die ersten Knoten gebunden werden. Diese Punkte haben aber schon uv Koordinaten. Folge: die circular letzten Segmente erhalten die gesamte map bis zur vorletzten Stelle aber rückwärts! Hier gut zu erkennen:



UPDATE 6.5. zu
(Ich schrieb:
Aber es kam gerade eben noch viel schlimmer. Da es keine Faces als Objekt gibt, sondern nur Indizes für die Eckpunkte, kann auch der Materialindex nicht an die Dreiecke (Faces) gebunden werden. Stattdessen müssen bei BufferGeometriy fortlaufende Gruppen von Knoten gebildet werden { start: Integer, count: Integer, materialIndex: Integer }
und mit .addGroup ( start, count, materialIndex ) eingefügt werden.
Da ich aber jedes Dreieck dynamisch mit einem anderen Material versehen kann, ist das nun ein echtes Problem. Da sehe ich kein "einmischen" mehr, das sprengt die Systematik, zumal eben statt der Faces alle Knoten einzeln sein müssen - sind sie aber nicht!
 
)

War wohl schon zu spät am Abend, habe mir jetzt nochmal den Quellcode von three.js zu CylinderBufferGeometry angesehen. Offenbar beziehen sich die Gruppen doch auf die Indizes und nicht die Positionen!? Dann geht es doch. Muss nun probieren.

Das uv- Problem kann ich mit extra Knoten an identischer Position irgendwie lösen. 

 
05.05.2017  
 




Antworten


Thementitel, max. 100 Zeichen.
 

Systemprofile:

Kein Systemprofil angelegt. [anlegen]

XProfan:

 Beitrag  Schrift  Smilies  ▼ 

Bitte anmelden um einen Beitrag zu verfassen.
 

Themenoptionen

334.566 Betrachtungen

Unbenanntvor 0 min.
HofK30.10.2024
Rschnett24.08.2024
Michael W.28.03.2024
Thomas Zielinski17.02.2024
Mehr...

Themeninformationen



Admins  |  AGB  |  Anwendungen  |  Autoren  |  Chat  |  Datenschutz  |  Download  |  Eingangshalle  |  Hilfe  |  Händlerportal  |  Impressum  |  Mart  |  Schnittstellen  |  SDK  |  Services  |  Spiele  |  Suche  |  Support

Ein Projekt aller XProfaner, die es gibt!


Mein XProfan
Private Nachrichten
Eigenes Ablageforum
Themen-Merkliste
Eigene Beiträge
Eigene Themen
Zwischenablage
Abmelden
 Deutsch English Français Español Italia
Übersetzungen

Datenschutz


Wir verwenden Cookies nur als Session-Cookies wegen der technischen Notwendigkeit und bei uns gibt es keine Cookies von Drittanbietern.

Wenn du hier auf unsere Webseite klickst oder navigierst, stimmst du unserer Erfassung von Informationen in unseren Cookies auf XProfan.Net zu.

Weitere Informationen zu unseren Cookies und dazu, wie du die Kontrolle darüber behältst, findest du in unserer nachfolgenden Datenschutzerklärung.


einverstandenDatenschutzerklärung
Ich möchte keinen Cookie