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



HofK
Die Funktion explode gibt es nun auch bei THREEf.

Die neuesten Versionen befinden sich auf meiner Seite und auf GitHub.



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

Dann ein wenig Abwechselung und eventuell konnte ich helfen.

Dort  [...]  war mal wieder eine einfache Frage - zu einer " slot machine" Spielautomat ? .

Im Ergebnis habe ich ein weiteres kleines Anfängerbeispiel.



Man kann es unter  [...]  bzw.  [...]  ausprobieren.

Man benötigt nur passende Grafiken - da gibt es andere Experten als mich! 

Mein Versuch:

 
15.11.2017  
 




HofK
HofK (14.11.2017)
Nachdem auch die letzte Naht geglättet war ...




... bei BufferGeometry!


Auch wenn Geometry abgeschafft werden soll - mittlerweile ist diese Variante soweit fertig. In three.js r88 funktioniert es prima und der Aufwand hielt sich in Grenzen. Ich konnte viele Passagen von indexed BufferGeometry kopieren und dann nur die entsprechenden Abwandlungen vornehmen.

Allerdings zeigt sich nun bei den Nähten ein Problem. Die Normalen werden im Face3-Objekt  [...]  gespeichert.

Constructor
Face3( a, b, c, normal, color, materialIndex )
a — Vertex A index.
b — Vertex B index.
c — Vertex C index.

normal — (optional) Face normal (Vector3) or array of vertex normals. If a single vector is passed in, this sets .normal, otherwise if an array of three vectors is passed in this sets .vertexNormals



Dabei noch in unterschiedlich möglicher Weise.

Benutzt man nun
g.computeVertexNormals(); // in this case by three.js and then ...

ist es nicht so einfach wie bei den Vertex-Normalen der BufferGeometry Anpassungen vorzunehmen und zu speichern.

Mal schauen, ob eine sinnvolle Lösung zu finden ist.

 
20.11.2017  
 




HofK
Habe die Nähte erst einmal beiseite gelegt und die Festlegung des Materialindex je face per String-Datenfeld ergänzt. Bei THREEp geht es ganz einfach nach der Reihenfolge der faces per Halbkugel, die Strings sind für bottom bzw. top (Süd/ Nord, wenn vorhanden) für jede Kugelschicht und für die Deckebene und den Keil (wenn vorhanden).

Damit ist der Umfang nun ähnlich wie bei THREEf und die Betaphase erreicht.



Ausprobieren unter  [...]  oder Code bei GitHub betrachten/ downloaden unter  [...] 
 
25.11.2017  
 




HofK
Mal wieder etwas Abwechslung - eine interessante 3D Sache. -----

In einem Beitrag bei discourse.threejs.org [...]  fand ich eine Spur zu einer Bibliothek zur "Mischung" von geometrischen Objekten. [...] 



Darunter kann man auf der Seite einen Beispielcode editieren und so seine selbst erstellten Resultate in 3D begutachten.





Ein Versuch.

Mit a.setColor(1, 1, 0); oder a.setColor(255, 255, 255);
sieht es gleich ganz anders aus.

Einfach mal probieren!
 
28.11.2017  
 




HofK
Weil bei der Variante mit den Kugelkoordinaten alle Dreiecke (faces) mit einerm fixierten Material versehen werden können, habe ich für die Zylindervariante THREEf nun noch den bisher dort fehlenden Boden und Deckel ergänzt.



Anders als bei der Kugel sind Boden und Deckel aber hier in der Konstruktion sehr eigenständig. Deshalb gibt es dafür zusätzlich zum Datenfeld fixedMaterial zwei extra Eigenschaften fixedMatTop und fixedMatBottom. Sie können eine Zeichenkette aus Ziffern 0 bis 9 enthalten. Platzhalter ist auch hier der Punkt. Damit werden die Materialien der Dreiecke / faces fixiert. Auch hier ist die Eingabe fehlertolerant. Also eine Zeichenkette .5.5 fixiert das zweite und vierte face auf Material 5. Überschreibt also ein Ergebnis der Funktionen materialBottom bzw. materialTop. Dabei kann Boden/ Deckel durchaus mehr als vier faces umfassen.

Bereits dort integriert:   [...] 

Noch nicht auf GitHub. 
 
30.11.2017  
 




HofK
Rotationen im Raum

sind eine für den Menschen nicht ganz so einfach zu überschauende Sache.

Gäbe es Vögel mit meschlicher Intelligenz, die sich three.js verschrieben hätten, wäre das für die primitiv. Sie leben im Raum und durch die Augenstellung haben sie Rundumblick. Wenn ein Mensch einen Salto mit Schraube macht, ist das schon Medaillen verdächtig!

Wenn ich also behaupte, mein räumliches Denken ist nicht schlecht, ist das sehr relativ.

In three.js werden für Rotationen sogenannte Quaternionen benutzt. Wer das Wort noch nie gehört hat, dem geht es wie mir bis vor einiger Zeit, obwohl ich mich sehr wohl seit langer Zeit mit Mathematik beschäftige. Die Mathematik ist aber so umfangreich, dass manche Teilbereiche nur in bestimmten Anwendungsbereichen eine Rolle spielen.

Robotik  [...] 

Autobranche DIN 70000  [...] 

Flugregler Seite 125  [...] 

Und weil es für mich neu war, habe ich nach einer guten Visualisierung gesucht. Viel war nicht zu finden und entsprach dann nicht meinen Bedürfnissen.

Aber einige Grundlagen habe ich so zusammengetragen.

Umrechnung  [...] 

Grafikprogrammierung (Folie 24)  [...] 

Quaternionen und Drehungen  [...] 

Understanding Quaternions  [...] 

Freie Rotation im Raum - Kamerasteuerung  [...] 

Ein schöner Umrechner - aber ohne Visualisierung. [...] 

______________________________________________

Dann also wieder mal selber gemacht.



Designed für Firefox.

Und dort ausprobieren / Code betrachten. [...]  bzw. [...] 

-----------

NACHTRAG 06.12.:

Tipp! Gibt man nicht normalisierte Werte in die Eingabefelder ein und wechselt zum Schieber, werden die Vektoren normalisiert (Länge 1).
 
05.12.2017  
 




p.specht

Tolle Zusammenstellung, gute Umsetzung! Da sucht man normalerweise einen Monat im Net - Danke!
 
XProfan 11
Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen, zB 'daß' statt 'das'...
06.12.2017  
 




HofK
Die "Rotations-Testperson" ist ja schick gemustert, was für den Zweck recht hilfreich ist, aber doch sehr einfach.

Sie besteht eben nur aus elementaren Körpern.

Kompliziertere Körper mit Funktionen zu erzeugen finde ich selbst sehr interessant - siehe oben. Aber es ist sicher nicht jedermanns Sache und nicht alle Körper lassen sich so herstellen.

Es gibt einige Tools um 3D Objekte zu erzeugen, so ist Blender sehr verbreitet.  [...] 
Als Anfänger wird man von der Oberfläche aber erst einmal glatt "erschlagen".

Einfacher aber natürlich weniger umfangreich sind z.B.  [...]  (sehr einfach) [...]  (Seite auch Deutsch, Software Englisch - etwas umfangreicher)

Allerdings bekam ich beim Export der benötigten .obj Dateien keine .mtl Datei für die Materialien. Diese "Bastelei" ist mir entweder zu langweilig oder zu anstrengend - nicht mein Ding.

Aber man kann auch fertige Objekte benutzen. Leider gibt es eine Vielfalt an Dateitypen. Bei three.js auf der Startseite  [...]  sind featured projects zu finden. So auch poly  [...] 

Dort kann man Objekte hoch- und einige auch runterladen. Nur habe ich wenige herunterladbare (Lizenz!) .obj Dateien ( plus .mtl Datei für das Material) gefunden.

Zur Lizenz:
Spinner
Hennadiy Kyseliov


Diesen Inhalt remixen
Dieser Inhalt wird unter einer CC-BY-Lizenz veröffentlicht. Wenn du den Autor namentlich nennst, kannst du diesen Inhalt kostenlos verwenden.




Nun fehlt noch ein kleines Script, um den Spinner beliebig in three.js zu verwenden. Das Problem sind wie immer sich schnell ändernde Statements in three.js. Ein gutes Beispiel  [...]   [...]  ist nach ca. 11 Monaten schon nicht mehr ganz aktuell. Es gibt Warnungen, läuft aber noch unter der aktuellen Revision 88.
Ganz so einfach ist das Beispiel aber auch nicht.

Das offizielle Beispiel in threejs.org ist für Anfänger wie meist zu komplex. Erst einmal Wichtiges ist schwer herauszufiltern.

Also habe ich radikal zusammengestrichen.

Dann bleibt nur der überschaubare Kern übrig.

Etwas gewöhnungsbedürftig:
Es wird in einer Funktion das Material geladen und in dieser Funktion dann das Objekt.

Wenn das Objekt erstellt wird, muss das zugehörige Material bekannt sein. Also verschachtelt man es.

var exampleObject = new THREE.Object3D();

var mtlLoaderExample = new THREE.MTLLoader( );

mtlLoaderExample.load(

'spiner.mtl', // Lizenz

function (materials) {

materials.preload();

var objLoaderExample = new THREE.OBJLoader( );

objLoaderExample.setMaterials( materials );

objLoaderExample.load(

'spiner.obj', // Lizenz

function (object) {

exampleObject.add(object);

}

);

}

);

scene.add( exampleObject );

Das komplette Beispiel:  [...]  bzw.  [...] 

_________________________________

Nachträge:
Da  [...]  gibt es einige obj Dateien mit Vorschaubild. Aber ohne Material!
---
Weitere siehe Beitrag vom 16.01.2018 weiter unten.
 
09.12.2017  
 




HofK
Wenn man eine Geometrie "von Hand" erzeugt, siehe Quelltext (Strg+U)  von  [...]  trägt man Werte für Positionen usw. in JavaScript Datenfelder ein. Man hat die Geometrie sozusagen voll im Griff und kann mal schnell einen Wert ändern.

Benutzt man nun aber mein Addon THREEf.js, so gibt man nur ein paar Funktionen als Parameter an und fertig ist die Geometrie.

Wie sieht die nun aber intern aus? Wie die Datenfelder? 

Weil ich neugierig bin, wollte ich mir das natürlich jetzt mal ansehen. Ausserdem dazu die Idee, per Funktionen erzeugte Geometrie nachträglich zu modifizieren. Das macht Sinn, wenn die Grundform klar ist und schnell durch Funktionen erzeugt werden kann, aber einige Kleinigkeiten sehr individuell gestaltet werden sollen. Und wenn man dazu nicht ein Modellierungstool wie Blender benutzen möchte - ich möchte nicht!

Deshalb habe ich ein kleines Script geschrieben. Es gibt die Datenfelder aus. Um zu sehen, ob die auch korrekt sind und als Vorbereitung zu Umsetzung der Idee zur Modifizierung der Geometrie, habe ich aber nicht die Zahlenwerte aneinandergereiht, sondern um sie herum auch den JavaScript Code zur Erzeugung der Geometrie per three.js mit generiert. Kopiert man nun diesen Code per Strg+A, Strg+C, Strg+V in eine leere Datei geo.js und bindet diese per
<script src="geo.js"></script>
in das Script mit der Ausgabe ein, erhält man nach Aktualisierung den Vergleich, wenn im Script noch

// skript geo.js definiert Geometrie geo
var me = new THREE.Mesh( geo, materials );
scene.add( me );
me.add( geo.quadLine );
me.position.x = 50;


zur Erzeugung der gedoppelten Geometrie 50 rechts ergänzt wird. Unten dran das zu kopierende JavaScript.



Der Quellcode:
<!DOCTYPE html>
<!--   *** modify THREEf geometries ***
/**
* @author hofk / https://sandbox.threejs.hofk.de/
*/
-->
<html lang="de">
<head>
<title> modify </title>
<meta charset="utf-8" />
</head>
<body>
<div id="webGL">  </div>
<div id="output"> output </div>
</body>
<script src="three.min.88.js"></script>
<script src="OrbitControls.js"></script>
<script src="THREEx.WindowResize.js"></script>
<script src="THREEf.js"></script>
<script src="geo.js"></script>
<script>
'use strict'
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 200000 );
camera.position.set( 0, 80, 200 );
var renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xeeeeee, 1 );
var container = document.getElementById('webGL' );
container.appendChild( renderer.domElement );
THREEx.WindowResize( renderer, camera );
var controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.enableZoom = true;
// material
var uvTex			= new THREE.TextureLoader().load( "uvgrid01.png" );
var waterlilyTex	= new THREE.TextureLoader().load( "waterlily.png" );
var side =  THREE.DoubleSide;
var materials = [// material index:
new THREE.MeshBasicMaterial( { transparent: true,  color: 0x00ff00, opacity: 0.7, 	side: side	} ),//  0 transparent
new THREE.MeshBasicMaterial( { map: uvTex, 					side: side	} ),//  1 uv grid
new THREE.MeshPhongMaterial( { color: 0xff0000, emissive: 0xff0000, side: side,  } ),//  2 red
new THREE.MeshPhongMaterial( { color: 0x00ff00, emissive: 0x00ff00, side: side, } ),//  3 green
new THREE.MeshPhongMaterial( { color: 0x0000ff, emissive: 0x0000ff, side: side, } ),//  4 blue
new THREE.MeshPhongMaterial( { color: 0xffff00, emissive: 0xffff00, side: side, } ),//  5 yellow
new THREE.MeshPhongMaterial( { color: 0xff00ff, emissive: 0xff00ff, side: side, } ),//  6 mgenta
new THREE.MeshPhongMaterial( { color: 0x00ffff, emissive: 0x00ffff, side: side, } ),//  7 cyan
new THREE.MeshBasicMaterial( { map: waterlilyTex,					side: side	} ),//  8 photo waterlily (free)
new THREE.MeshPhongMaterial( { color: 0x7755ff, emissive: 0x4433dd, side: side	} ),//  9 color
new THREE.MeshPhongMaterial( { color: 0x444444, emissive: 0x333333, side: side	} )// 10 grey
];
var sun1 = new THREE.DirectionalLight();
sun1.intensity =  0.6;
sun1.position.set(50, 200, 300);
scene.add(sun1);
var sun2 = new THREE.DirectionalLight();
sun2.intensity =  0.5;
//sun2.position.set(-50, -200, 300);
sun2.position.set(0, 0, 0);
scene.add(sun2);
// geometry

var parameters = {

    height: 20,
    quadLine: true,
    quadColor: 0xff00ff,
    circOpen:	true,
    unrollCover:	function ( v, t ) { return 0.2 },
    radiusSegments: 2,
    heightSegments: 1,
    rCircHeight: function ( u, v, t ) { return u + v },
    materialCover:	function ( u, v, t ) { return 0 },

}

var geometry = new THREE.BufferGeometry();
geometry.createMorphGeometry = THREEf.createMorphGeometry;
geometry.createMorphGeometry( parameters );
// ........... start output JavaScript Code ....................................................
var vc3 = geometry.vertices.length;
var uvc2 = geometry.uvs.length;
var fc = geometry.faceIndices.length / 3;
output.innerHTML = "var geo = new THREE.BufferGeometry(); <br />";
output.innerHTML += "geo.faceIndices = new Uint32Array( [ " + geometry.faceIndices + " ] ); <br /> ";
output.innerHTML += "geo.vertices = new Float32Array( [ ";

for ( var v = 0; v < vc3 ; v ++ ) {

    output.innerHTML += geometry.vertices[ v ];
    output.innerHTML += v < vc3 - 1  ? ", " : "";

}

output.innerHTML += " ] ); <br /> ";
output.innerHTML += "geo.normals = new Float32Array( [ ";

for ( var v = 0; v < vc3 ; v ++ ) {

    output.innerHTML += geometry.normals[ v ];
    output.innerHTML += v < vc3 - 1  ? ", " : "";

}

output.innerHTML += " ] ); <br /> "
output.innerHTML += "geo.uvs = new Float32Array( [ ";

for ( var v = 0; v < uvc2 ; v ++ ) {

    output.innerHTML += geometry.uvs[ v ];
    output.innerHTML += v < uvc2 - 1  ? ", " : "";

}

output.innerHTML += " ] ); <br /> "
output.innerHTML += "geo.setIndex( new THREE.BufferAttribute( geo.faceIndices, 1 ) ); <br /> geo.addAttribute( 'position', new THREE.BufferAttribute( geo.vertices, 3 )); <br />geo.addAttribute( 'normal', new THREE.BufferAttribute( geo.normals, 3 )); <br /> geo.addAttribute( 'uv', new THREE.BufferAttribute( geo.uvs, 2 ) );<br /> ";
output.innerHTML += "var geoG = [ ";

for ( var f = 0, p = 0; f < fc ; f ++, p += 3 ) {

    output.innerHTML += geometry.groups[ f ].start + ", " + geometry.groups[ f ].count + ", " + geometry.groups[ f ].materialIndex ;
    output.innerHTML += f < fc - 1  ? ", " : "";

}

output.innerHTML += " ]; <br /> ";
output.innerHTML +=  " for ( var f = 0, p = 0; f < " + fc + "; f ++, p += 3 ) { geo.addGroup( geoG[ p ], geoG[ p + 1 ], geoG[ p + 2 ] ); } <br /> ";

if ( geometry.quadLine ) {

    output.innerHTML += "geo.lineGeometry = new THREE.BufferGeometry(); <br />";
    output.innerHTML += "geo.quadLine = new THREE.Line( geo.lineGeometry, new THREE.LineBasicMaterial( { color: " + geometry.quadColor + "} ) ); <br />";
    output.innerHTML += "geo.linePositions = new Float32Array( [ ";

    for ( var v = 0; v < 2 * vc3 ; v ++ ) {

        output.innerHTML += geometry.linePositions[ v ];
        output.innerHTML += v < 2 * vc3 - 1  ? ", " : "";

    }

    output.innerHTML += " ] ); <br /> ";
    output.innerHTML += "geo.lineGeometry.addAttribute( 'position', new THREE.BufferAttribute( geo.linePositions, 3 ) );  <br />";

}

// .............. end output JavaScript Code .......................................................
// mesh
var mesh = new THREE.Mesh( geometry, materials );
scene.add( mesh );
mesh.add( geometry.quadLine );
mesh.colorsNeedUpdate = true;
//...  skript geo.js def. Geometry geo ............ ......
var me = new THREE.Mesh( geo, materials );
scene.add( me );
me.add( geo.quadLine );
me.position.x = 50;
//..........................................................
animate();
//-----------------

function animate() {

    requestAnimationFrame( animate );
    renderer.render( scene, camera );
    controls.update();

}

</script>
</html>
 
11.12.2017  
 




HofK
Wenn man die Geometrie modifizieren möchte, benötigt man den 3D Zugriff per Maus und einige Informationen. Dazu konnte ich mein Raycaster Beispiel  [...]  als Grundlage verwenden.

Raycaster ermittelt so manche Werte.



Wie bei der Vorstellung des Beispiels (erste Version 29.10.2016 , deutsch) besprochen, werden Positionen im lokalen Speicher des Browsers abgelegt. Neuere Browserversionen ermöglichen nun den Zugriff! Da kann man nach den gespeicherten Werten sehen und sie bei Bedarf auch löschen. Mit Firefox sieht das beim Beispiel so aus.



Also mal schauen, was andere Seiten da so abladen!


Kein Geheimnis:
Laufende Projekte bearbeite ich aus einer RAM-Disk heraus. Kein Festplattenlärm, SSD schonen und superschnell.
 


Wie man im oberen Bild erkennt, trat bei indices ein Fehler auf.

undefined


Nach Recherche fand ich ein Problem und das für mich erstaunlicherweise bei BufferGeometry faceIndex funktioniert.

Das habe ich mal als Frage bei discourse.threejs.org  gestellt: [...] 

Soeben kam schon eine Antwort herein!
 
 
13.12.2017  
 




HofK
Mittlerweile habe ich ein wenig an der Manipulation der Positionen der Geometrie herumgewerkelt. Das Prinzip ist eigentlich ganz einfach, aber wie so oft steckt der im Detail und hat mir manchmal dazwischengefunkt.

Man berechnet die Richtung und den Abstand (Vektor) des Schnittpunktes des Strahls von der Kamera mit der Hilfsebene (raycaster.intersectObjects( ... ) zu den Ecken a, b, c des Dreiecks. Bewegt man dann die Maus, werden die Eckpunkte entsprechend mitbewegt, indem man den Vektor addiert.

Der noch unfertige Arbeitsstand ist aktuell als Video dort  [...]  (Mittlerweile dort neuere Videos!) zu sehen.Die Reaktion der Hilfsebene auf die Mausbewegung macht mir noch Probleme, da ist Feinarbeit angesagt, oder es muss etwas am Grundkonzept geändert werden.

Ich hatte mit gridHelperXY = new THREE.GridHelper( ... noch insgesamt drei Hilfsgitter eingeblendet, aber dann war die Mausreaktion "Glückssache".

Die eigentliche Manipulation der Werte im Datenfeld ist sehr überschaubar:

Dabei ist handle... der Schnittpunkt auf der Hilfsebene senkrecht zur Kamera und paV, pbV und pcV die Vektoren von dort zu den Eckpunkten.

 
18.12.2017  
 




ByteAttack
Ob sich das wirklich hier im Forum wirklich anschaut? Wage ich zu bezweifeln... ich persönlich finde deine Arbeit toll!
 
XProfan X3
Website:  [...] 
Facebook:  [...] 
19.12.2017  
 




Antworten


Thementitel, max. 100 Zeichen.
 

Systemprofile:

Kein Systemprofil angelegt. [anlegen]

XProfan:

 Beitrag  Schrift  Smilies  ▼ 

Bitte anmelden um einen Beitrag zu verfassen.
 

Themenoptionen

333.081 Betrachtungen

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