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 15 -



HofK
Hat man einen Spiegel, kann man Exponate auch von hinten betrachten. Und man kann sich selbst sehen.

Also musste einer her!

Die Vorlage liefert  [...]  . Das Beispiel benutzt das zusätzliche Script Reflector.js  [...]  .

Dieses Script eingebunden und mit

genutzt. Ein rahmenloser Spiegel schräg in der Ecke. Er reicht bis zum Boden.



Reflector.js benutzt eine virtuelle Kamera am Standort des Spiegels. Sie nimmt die Scene von dort auf.
var virtualCamera = new THREE.PerspectiveCamera();

Es wird ein Shader benutzt um das Spiegelbild darzustellen.
var shader = options.shader || THREE.Reflector.ReflectorShader;
...
var material = new THREE.ShaderMaterial( {
uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader,

} );



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

Damit man sich im Raum ordentlich bewegen kann, um Dinge auch näher zu betrachten, benötigt man eine Möglichkeit die Augen des virtuellen Besuchers ( Kamera, die 3D Scene in 2D abbildet) leicht zu steuern. Der Besucher muss in alle Richtungen gehen können, sich drehen, bücken und strecken und die Augen nach oben und unten richten können.

Dazu habe ich einen virtuellen Controler gebastelt. Er ist unaufdringlich transparent, kann frei im Browserfenster bewegt werden und wenn die Maus über eine der aktiven kreisförmigen Bereiche kommt, wird das Symbol kräftig und es startet die jeweilige Bewegung. Sie hört auf, wenn die Maus den Bereich verlässt. Ein Klick ist nicht nötig.



Wie man sieht ( extra zum Teil über die graue Wand geschoben!) , sind noch nicht alle Kreise mit Symbolen und Funktionen belegt.

Der Controler ist modular aufgebaut, man kann Kreise auch vollständig ausblenden. Es werden Icons 32x32 und 16x16 oder in der Maxivariante 64x64 und 32x32 benötigt. Diese müssen so gestaltet sein, dass sie in den Kreis passen, dürfen also nicht die Ecken benutzen.

Die Lücken zwischen den Kreisen sind ausreichend groß, um mit der Maus ohne eine Funktion auszulösen stressfrei zu navigieren.
 
31.03.2018  
 




HofK
Ostern

ist ja auch die Zeit der Suche.

Allerdings habe ich nur etwas sortiert und nicht gesucht.
Aber trotzdem etwas gefunden!



Nein, das ist nicht meine neueste three.js - Kreation die ich verlegt habe.

Dieses Blatt habe ich vor ziemlich genau 30 Jahren auf meinem seinerzeit hochmodernem 8 Nadel Drucker LX 800 ausgedruckt.

Es lag in diesem Bestseller,



den ich einige Monate zuvor mit Staunen ob der ungeahnten Möglichkeiten in kürzester Zeit förmlich "verschlungen" hatte.

Die 3D Grafik ist programmiert auf dem ATARI 520ST mit GFA Basic 3.0 mit integriertem Editor, was weit mehr als ein BASIC war. Einige Features vermisse ich heute bei JavaScript und anderen Sprachen! Auch hatte das grafische Betriebssystem einige Vorzüge gegenüber Windows, das da noch nicht aktuell war.

Eine Sache werde ich nicht vergessen. Um Daten zu übertragen habe ich ein serielles Verbindungskabel ATARI zu PC (DOS) gebastelt.

Die Schnittstelle auf dem ATARI zu programmieren ging mit wenigen gut dokumentierten Befehlen recht zügig, unter DOS hat das Nerven gekostet und mit Fehlversuchen gedauert. Aber ich war (bin) hartnäckig und konnte so jahrelang Textdateien (WLAN war noch nicht!) schnell übertragen.

Nicht das technisch bessere setzt sich immer durch, oft auch Schrott!



FROHE OSTERN!


 
01.04.2018  
 




p.specht

Frohe Ostern auch Dir !
 
XProfan 11
Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen, zB 'daß' statt 'das'...
01.04.2018  
 




HofK
... einen virtuellen Controler gebastelt ...

Der Controler war wirklich nur gebastelt. Es ging mir erst einmal lediglich um die Funktionsweise im Schauraum.

Eigentlich wollte ich mich ja mit three.js befassen, aber man kommt nicht umhin auch etwas Javascript für DOM/HTML/CSS zu machen.

Und das ist ein historisch gewachsener Syntax-Sumpf.
Als ich seinerzeit erstmals HTML begegnet bin, gefiel mir das als Programmierer überhaupt nicht. Aber mit Hypertexten hatte ich nichts zu tun und dachte, das berührt mich nicht. Auf Dauer falsch gedacht. Mit der Integration von JavaScript bin ich mittendrin.

Warum ich gerade "jammere"?
 


Mein Controler ist mit Bildern bestückt, also img -tags. Diese sind an span -tags gebunden, um mit einen passenden Randradius den Kreis zu erzeugen.

Nun muss man einen Ereignislauscher benutzen.

navigationControl.addEventListener('mouseover', mouseover );


Was liegt näher, als nun in der Funktion function mouseover( event ) die Identifikationsnummer zu ermitteln und auf das Ereignis bezogen auf das auslösende Element zu reagieren. img -tags haben standardmäßig kein id Attribut.

Wenn man die span und img -tags mit JavaScript erzeugt, muss man die id sowieso selbst generieren. Erlauscht wird dann die "oben" liegende. Ist ein Bild auf dem span gibt es nur die Bild id. Ist logisch, aber man muss es erst mal finden, wenn man nicht so tief in HTML/CSS drinsteckt.


imgs[ i ].setAttribute('id', i.toString( ) + ' imgId' );

function mouseover( event ) {

console.log( 'event.target.id ' + event.target.id );
var idx = parseInt( event.target.getAttribute( 'id' ) );

if ( idx > 0 ) { ... irgendetwas zur id von span oder Bild ...


Als Wegweiser durch den HTML/CSS/DOM/JavaScript Dschungel ist mir immer mehr  [...]  mit recht guter interner Suche sehr hilfreich. Hier z.B. unter anderem  [...] 

So einfach konfiguriert man den Controler:







Das kommt heraus (andere Farben für Center):



Die äußeren drei span's haben kein Bild.
 
05.04.2018  
 




HofK

Mit dem Controler bewegt sich der virtuelle Besucher zügig durch den Ausstellungsraum.


Die unsichtbare Kamera sind seine Augen. Damit der Besucher sich selbst im Spiegel erblicken kann, braucht er einen sichtbaren Körper. Zum Test reicht erst einmal ein einfaches Gitter. Da die Augen mitten im Körper sitzen, sieht er nicht nur sein Spiegelbild, sondern auch noch einige originale Körperlinien.



Wenn der Besucher nun flott im Raum umher geht, knallt er ganz schnell mal gegen einen Einrichtungsgegenstand oder eine Wand. Er geht sogar durch Wände! Das muss verhindert werden.

Der erste Gedanke war Kollisionserkennung. Dazu habe ich ein einfaches Beispiel auf threejs.hofk.de  [...] 

Also den Code angepasst.
Vorbereitet für mehrere Besucher. Hier erst einmal Besucher 0 - visitor...[ 0 ]

function detectCollision( cIdx ) {

var ray;
var originPoint = visitorMeshes[ 0 ].position.clone();
var localVertex = new THREE.Vector3( );
var globalVertex;
var directionVector;
var distance = Infinity;

for ( var j = 0; j < visitorGeometries[ 0 ].getAttribute('position').array.length; j += 3 ) {

localVertex.x = visitorGeometries[ 0 ].getAttribute('position').array[ j ];
localVertex.y = visitorGeometries[ 0 ].getAttribute('position').array[ j + 1 ];
localVertex.z = visitorGeometries[ 0 ].getAttribute('position').array[ j + 2 ];
globalVertex = localVertex.applyMatrix4( visitorMeshes[ 0 ].matrix );
directionVector = globalVertex.sub( visitorMeshes[ 0 ].position );
ray = new THREE.Raycaster( originPoint, directionVector.clone().normalize() );
collisionResults = ray.intersectObjects( collidableMeshes );

if ( collisionResults.length > 0 ) distance = collisionResults[0].distance;

return distance;

}

}

Die Sache hat aber einen entscheidenden Haken. Es sind anders als in der kleinen Vorlage mit zwei Wänden sehr viele Objekte zu überprüfen. Um kleinere Gegenstände zu erfassen, muss das Hilfsgitter des Besuchers auch ausreichend engmaschig sein. Befindet sich die Maus über einem Kreis des Controlers, muss unablässig die Kollisionserkennung durchgeführt werden. Aus dem flotten Besucher wird eine Ruckelschnecke.

Da ich keine brauchbare Idee habe den Aufwand drastisch zu reduzieren, nun ein neuer Ansatz.

Wie im realen Leben wird auch der virtuelle Besucher in seiner Bewegungsfreiheit eingegrenzt. Für Menschen nimmt man Seile oder Absperrgitter, für Mähroboter einen eingegrabenen Begrenzungsdraht und für virtuelle Besucher eine Anzahl von Rechtecken, definiert durch zwei Ecken.
<textarea id="visitorAreas"  style="width: 620px; height: 100px " > [
<!-- Besucher, Rechtecke x0,z0, < x1,z1 -->
[ 1, 1, 8, 6 ],
[ 8, 2, 9, 5 ],
[ 9, 2.5, 10, 4.5 ]
] </textarea>

Ein Späher schaut vorab, ob die nächste Bewegung über die Begrenzung hinausgeht. Wenn nicht, geht es nun wieder zügig weiter. Der Prüfaufwand ist gering.
 
09.04.2018  
 




HofK
Schaut man sich die Navigationskommandos im vorletzten Beitrag genauer an, wird deutlich, dass die Richtungen auf den Raum bezogen sind. Dreht sich nun der Besucher, ist das für die Navigation ungeeignet. Aus vorwärts im Raum (Richtung negative z Achse) wird dann z.B. auch mal schräg zurück für den Besucher.

Die Anpassung lässt sich leicht mit sin() und cos() bewerkstelligen. Dabei habe ich gleich noch neu strukturiert und einen Geschwindigkeitsfaktor eingefügt.





Der Parameter obj gestattet nun verschiedene Objekte zu navigieren. So braucht es auch keine kopierten Kommandos für den Scout mehr.

Aus eval( navActionCommands[ i ] ); wird einfach
navActionCommands[ i ]( camera ); oder navActionCommands[ i ]( scout );
 
14.04.2018  
 




HofK
Der Raum hat Öffnungen nach draußen. Bisher war da nur die Hintergrundfarbe. Wenn man hinaus schaut, möchte man aber auch die Umgebung sehen.

Das lässt sich ganz einfach nach dem Beispiel  [...]  auf meiner Seite erreichen.

Diesmal ist es keine Linse, sondern der Schauraum, der sich in der Box befindet. Die Cubemap ist erst einmal wieder von der Seite humus.name [...] 

Solche Cubemaps kann ich nicht erzeugen. Für mein Beispiel reicht aber eine einfachere Variante. Die Schwierigkeit besteht ja darin, dass die sechs Teilfotos an den Rändern nahtlos zueinander passen müssen. Aber nur, wenn der Blick auf die Ränder fallen kann. Da der Raum aber nur wenige Öffnungen hat, lässt es sich so einrichten, dass der Blick immer komplett auf einer der sechs Seiten bleibt. Wenn man keine Pfahlhütte mit Bodenloch baut, benötigt man auch kein sinnvolles Bild für negatives y. Hat man ein Dachfenster, ist ein Wolkenbild für positives y unabdingbar. Aber solche Einzelbilder sind ja kein Problem.

Der Blick in die Natur:




Im vergrößerten Spiegel wird auch der Wald mit gespiegelt.



Näher herangetreten ist mehr Wiese zu sehen.



Hier könnte nan meinen, rechts eine Kante der Box zu haben. Ist aber nicht!

Das komplette Bild der Seite:



---
Einfach ein Bild wie die "Königin der Nacht" in den Raumöffnungen zu platzieren hat keinen 3D Effekt. Der Besucher sieht nur mit dieser Methode wie auch real verschiedene Ausschnitte der Umgebung.
 
15.04.2018  
 




HofK
Der Frühling kommt, die (Computer)Zeit wird knapper.

Habe einige Varianten des Ladens von Objekten ausprobiert, - das dauert.

Dann die Spiegel näher untersucht.

Es geht auch eine Doppelspiegelung. Dazu setzt man in new THREE.Reflector ...

recursion: 1



Bei 0 bleibt der Spiegel im Spiegel Dunkel.



Allerdings konnte ich keine Mehrfachspiegelung erreichen. Geht eventuell nicht, der Rechenaufwand wäre auch enorm.
 
21.04.2018  
 




HofK
Manchmal benötigt man statt einer Tür mit Zarge einen Torbogen.

Ein wenig Sinus und Cosinus sind da wieder hilfreich.

Aus den Koordinaten der Punkte p1 links unten, p2 links oben, p3 rechts unten und p4 rechts oben werden einige Hilfswerte berechnet. (c ist Center)

Nach 36 Koordinatenwerten für die Seiten kommen die Bögen.
...
cx = ( p2x + p4x ) / 2;
cy = p2y - radius;
cz = ( p2z + p4z ) / 2;
cpx = Math.abs( p3x - p1x ) / 2;
cpz = Math.abs( p3z - p1z ) / 2;

for( var j = 0; j < 36; j ++ ) {

    // idx = j * 36 + 36;  //4 faces 9*4
    idx = j * 18 + 36;// 2 faces test ohne Innenwoelbung
    archwayPositions[ i ][ idx ] = p2x - dx;
    archwayPositions[ i ][ idx + 1 ] = p2y;
    archwayPositions[ i ][ idx + 2 ] = p2z - dz;
    archwayPositions[ i ][ idx + 3 ] = cx - dx - cpx * Math.cos( Math.PI / 2 * j / 36 );
    archwayPositions[ i ][ idx + 4 ] = cy + radius * Math.sin( Math.PI / 2 * j / 36 );
    archwayPositions[ i ][ idx + 5 ] = cz - dz + cpz * Math.cos( Math.PI / 2 * j / 36 );
    archwayPositions[ i ][ idx + 6 ] = cx - dx - cpx * Math.cos( Math.PI / 2 * ( j + 1 ) / 36 );
    archwayPositions[ i ][ idx + 7 ] = cy + radius *  Math.sin( Math.PI / 2 * ( j + 1 ) / 36 );
    archwayPositions[ i ][ idx + 8 ] = cz - dz + cpz * Math.cos( Math.PI / 2 * ( j + 1 ) / 36 );
    archwayPositions[ i ][ idx + 9 ] = p2x + dx;
    archwayPositions[ i ][ idx + 10 ] = p2y;
    archwayPositions[ i ][ idx + 11 ] = p2z + dz;
    archwayPositions[ i ][ idx + 12 ] = cx + dx - cpx * Math.cos( Math.PI / 2 * j / 36 );
    archwayPositions[ i ][ idx + 13 ] = cy + radius * Math.sin( Math.PI / 2 * j / 36 );
    archwayPositions[ i ][ idx + 14 ] = cz + dz + cpz * Math.cos( Math.PI / 2 * j / 36 );
    archwayPositions[ i ][ idx + 15 ] = cx + dx - cpx * Math.cos( Math.PI / 2 * ( j + 1 ) / 36 );
    archwayPositions[ i ][ idx + 16 ] = cy + radius *  Math.sin( Math.PI / 2 * ( j + 1 ) / 36 );
    archwayPositions[ i ][ idx + 17 ] = cz + dz + cpz * Math.cos( Math.PI / 2 * ( j + 1 ) / 36 );

}


Zum Test der Koordinaten steht der unfertige Torbogen schräg mitten im Raum.

 
25.04.2018  
 




HofK
Der Code bedurfte noch ein wenig der Optimierung und die Wölbung war noch zu generieren. Ebenso die Unterstützung von Multimaterial. Die Untergliederung habe ich von 36 auf 24 reduziert. Das reicht völlig für den Viertelkreis. Durch die Funktion kann die linke und rechte Seite erzeugt werden.
function setArchawayPositions ( px, py, pz ) {

    // initial
    var cosj = 1;
    var apy = cy;
    var sinj1, cosj1, apy1;

    for( var j = 0; j < 24; j ++ ) {

        sinj1 = Math.sin( Math.PI / 2 * ( j + 1 ) / 24 );
        cosj1 = Math.cos( Math.PI / 2 * ( j + 1 ) / 24 );
        apy1 = cy + radius * sinj1 ;
        archwayPositions[ i ][ idx ] = px - dx;
        archwayPositions[ i ][ idx + 1 ] = py;
        archwayPositions[ i ][ idx + 2 ] = pz - dz;
        archwayPositions[ i ][ idx + 3 ] = cx - dx - cpx * cosj;
        archwayPositions[ i ][ idx + 4 ] = apy;
        archwayPositions[ i ][ idx + 5 ] = cz - dz + cpz * cosj;
        archwayPositions[ i ][ idx + 6 ] = cx - dx - cpx * cosj1;
        archwayPositions[ i ][ idx + 7 ] = apy1;
        archwayPositions[ i ][ idx + 8 ] = cz - dz + cpz * cosj1;
        archwayPositions[ i ][ idx + 9 ] = px + dx;
        archwayPositions[ i ][ idx + 10 ] = py;
        archwayPositions[ i ][ idx + 11 ] = pz + dz;
        archwayPositions[ i ][ idx + 12 ] = cx + dx - cpx * cosj;
        archwayPositions[ i ][ idx + 13 ] = apy;
        archwayPositions[ i ][ idx + 14 ] = cz + dz + cpz * cosj;
        archwayPositions[ i ][ idx + 15 ] = cx + dx - cpx * cosj1;
        archwayPositions[ i ][ idx + 16 ] = apy1;
        archwayPositions[ i ][ idx + 17 ] = cz + dz + cpz * cosj1;
        archwayGeometries[ i ].addGroup( 3 * idx / 9 , 3 * 2, 2 );
        // Woelbung
        archwayPositions[ i ][ idx + 18 ] = cx - dx - cpx * cosj;
        archwayPositions[ i ][ idx + 19 ] = apy;
        archwayPositions[ i ][ idx + 20 ] = cz - dz + cpz * cosj;
        archwayPositions[ i ][ idx + 21 ] = cx + dx - cpx * cosj;
        archwayPositions[ i ][ idx + 22 ] = apy;
        archwayPositions[ i ][ idx + 23 ] = cz + dz + cpz * cosj;
        archwayPositions[ i ][ idx + 24 ] = cx - dx - cpx * cosj1;
        archwayPositions[ i ][ idx + 25 ] = apy1;
        archwayPositions[ i ][ idx + 26 ] = cz - dz + cpz * cosj1;
        archwayPositions[ i ][ idx + 27 ] = cx + dx - cpx * cosj;
        archwayPositions[ i ][ idx + 28 ] = apy;
        archwayPositions[ i ][ idx + 29 ] = cz + dz + cpz * cosj;
        archwayPositions[ i ][ idx + 30 ] = cx + dx - cpx * cosj1;
        archwayPositions[ i ][ idx + 31 ] = apy1;
        archwayPositions[ i ][ idx + 32 ] = cz + dz + cpz * cosj1;
        archwayPositions[ i ][ idx + 33 ] = cx - dx - cpx * cosj1;
        archwayPositions[ i ][ idx + 34 ] = apy1;
        archwayPositions[ i ][ idx + 35 ] = cz - dz + cpz * cosj1;
        archwayGeometries[ i ].addGroup( 3 * (idx + 18 ) / 9, 3 * 2, 1 );
        idx += 36
        cosj = cosj1;
        apy = apy1;

    }

}


 
28.04.2018  
 




p.specht

Langsam wird´s ja richtig wohnlich bei Dir! Tolle Sache!
 
XProfan 11
Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen, zB 'daß' statt 'das'...
28.04.2018  
 




HofK
Soll ja eigentlich ein Ausstellungsraum werden. Aber gemütliche Sitzmöbel kann man auch reinstellen. Braucht man nur die passenden 3D Modelle.
..............................................................................................................

Mein Problem war jetzt aber noch einmal die Kameraführung. Die Kamera soll wie das menschliche Auge im Raum agieren. Die Variante von vor drei Wochen war noch unvollständig.

Nach einigen Versuchen hatte ich eine Lösung.  [...]  Die gefiel mir aber selbst nicht so richtig. (Strg U für Code)

Deshalb habe ich bei Discourse eine Frage formuliert. [...] 
Keine zwei Stunden später hatte ich von prisoner849 schon die erste Antwort. Später noch DIE Lösung.

Die neue Lösung ist im Code wesentlich kompakter, da sie mehr Methoden von THREE.js benutzt. [...]  Die Funktion selbst ist identisch.

Zum Test wird die Bewegung hier mit der Tastatur gesteuert und man bewegt sich in der Landschaft. 
 
04.05.2018  
 




Antworten


Thementitel, max. 100 Zeichen.
 

Systemprofile:

Kein Systemprofil angelegt. [anlegen]

XProfan:

 Beitrag  Schrift  Smilies  ▼ 

Bitte anmelden um einen Beitrag zu verfassen.
 

Themenoptionen

332.849 Betrachtungen

Unbenanntvor 0 min.
HofK vor 23 Tagen
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