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



HofK
Wer die Wahl hat, hat die Qual!

Es gibt so einige Möglichkeiten an der Grundform Kugel herumzuwerkeln.

Was soll man da nehmen

Nach Boden und Deckel habe ich probiert die Kugelkeile zu schließen.



Das funktioniert ohne großen Aufwand, wenn man die faces mit den vorhandenen vertices bildet. Da ich vorerst mit indexed BufferGeometry arbeite, wird aber sofort das Problem mit dem uv-Mapping deutlich. Die vertices haben bereits uv's und so ergibt sich die Verzerrung der Textur.

Beim Boden / Deckel am Pol ist das ja korrekt, wie man bei den Bildern der letzten Beiträge erkennt. Aber Boden / Deckel als Gegenstück zum Pol ergeben auf diese Art eine spiegelbildliche Textur - im Bild zu erkennen. Bei der "abgewählten" Geometry hat man das Problem nicht, da die uv's bei den faces gespeichert werden.

Bei BufferGeometry gibt es nur vertex uv's. Man muss also alle betroffenen vertices bei selber Lage - zeitabhängig in morphVertices() - doppeln und damit die neuen faces bilden. Dann kann man sogar eine eigene Textur aufbringen. Will man das? Ein erheblicher Mehraufwand!

Dabei: Warum die Geometry trotz aller Theorie und Absicht flotter ist, weiß ich immer noch nicht.    [...]  [...] 

Ehe ich mich entscheide, werde ich erst einmal schauen, wie ich die Kugel breitquetschen kann. Wie bei THREEf unrollCover wird der Radius auf dem die verices liegen immer größer, bis fast unendlich. Dann gibt es hier wenn gleichmäßig gequetscht wird schließlich zwei Kreise (Süd / Nord) mit dem Radius r * PI/2.

squeeze,// function ( v, t )// 0 sphere to 1 flat circle


Das funktioniert anders als stretchSouth / stretchNorth
Da wird nur die y Koordinate per verändertem Radius manipuliert.
function xyzCalculation( south_north, phi, theta, thetaY ) { 

r = g.radius * g.rPhiTheta( nji, ni, t );

x = r * Math.cos( theta ) * Math.cos( phi ) + g.radius * g.moveX( nji, ni, t );

z = - r * Math.cos( theta ) * Math.sin( phi ) + g.radius * g.moveZ( nji, ni, t );

r *= ( south_north === SOUTH ? g.stretchSouth( nji, ni, t ) : g.stretchNorth( nji, ni, t ) ) ;
y = r * Math.sin( thetaY ) + south_north * gap + g.radius * g.moveY( nji, ni, t );

}
 
23.08.2017  
 




p.specht

Wahnsinn, was da alles geht!
 
XProfan 11
Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen, zB 'daß' statt 'das'...
25.08.2017  
 




HofK
HofK (23.08.2017)
Ehe ich mich entscheide, werde ich erst einmal schauen, wie ich die Kugel breitquetschen kann.


...habe aber doch noch ein wenig rumprobiert und bin hängen geblieben.

Also nicht gequetscht, sondern erst gedeckelt.

Da vertices der Kugel, des Deckels und der Seite auf identischen Positionen liegen, sind bei der Entwicklung Fehler schwer zu erkennen. Deshalb verschiebe ich in der Probephase einfach eine Koordinate:



Dann wird es zusammengefügt.



und die Zahlen liegen übereinander.

Zwischenzeitlich gab es auch wieder "Pannen" im Leben neben dem Computer - das ist immer hinderlich. Wenn der Herd kaputt ist, ist Arbeit angesagt und essen ist wichtiger als three - und mein Note 2 ist nur noch als Textur zu gebrauchen.



Jetzt entwickelt sich die Seite der Nordhalbkugel, vertices sind schon per Zahl erkennbar. Die faces und uv's fehlen noch.
Die Sache ist doch erheblich verzwickter als beim Zylinder. Einmal durch die Kugelkoordinaten und dann durch die Kugelhälften.



Übrigens zeigt  [...]  (Nachtrag: nach einem Jahr dann unter All Time) dass ein gewisses Interesse besteht - also durchboxen.

Sucht man bei  [...]  nach three.js (sortiert nach Relevanz und Popularität) findet man die alten Beispiele recht weit vorne, obwohl die Aufrufzahl eher bescheiden ist.

Sollte da tatsächlich ein Mensch oder eine künstliche Intelligenz draufschauen?

Wenn der Code vorzeigbar ist, landet er auf GitHub. 
 
07.09.2017  
 




HofK
Nach einigen Fehlversuchen und auch Änderungen am vorhandenen Code ist nun THREEp.js ( rev 87.1 alpha ) auf GitHub  [...]  und auch schon bei  [...]  gepostet.

Übrigens nutze ich neuerdings deepl  [...]  als Übersetzungshilfe. Macht sich besser als Google Translator.

Das habe ich ( mit nachträglichen eigenen Anpassungen - die Fachtermini sind immer ein Problem) übersetzt:

THREEp.js. - eine erweiterte Alpha Version ist nun auf GitHub verfügbar.

- Es funktioniert mit three.js r87.
- Die Kugelkeile können an der Seite geschlossen werden (default).
- Die Äquator Lücke ist nun als Funktion verfügbar.

Mit der Äquator Lücke - nun als Funktion - öffnet und schließt ein kleines Monster sein Maul. Mit Parameter t - Zeit. 

screenshots exampleA2.html

Die Bilder mal nur da:   [...] 

var parameters = {

equator: 4,

equatorGap: function( u, t ) { return 0.5 *( 1 + Math.cos( 6.28 * u)) *( 0.5 - u )*( 0.5 - u ) * ( 1 + Math.sin( t ) ) },
stretchSouth: function ( u, v, t ) { return ( 1 + Math.cos( 6.28 * u)) *( 0.5 - u )*( 0.5 - u ) * ( 1 + Math.sin( t ) ) },

wedges: 11,
usedWedges: 8,

topCircle: 7,
withTop: true,

bottomCircle: 3,
withBottom: true,

}
 
13.09.2017  
 




HofK


Die Quetschung ist doch komplizierter, als ich mir das so vorgestellt hatte:
Einfach draufdrücken und fertig. 

Deshalb habe ich nach einigen Bleistift- Kritzeleien ganz gegen meine Art doch mal eine halbwegs saubere Skizze fabriziert:



Beispielsweise unter  [...]  findet man ausreichend viele Formeln zur Berechnung.

Der Bogen des Viertelkreises mit dem Radius 1 muss auf den Bogen des halben Kreissegments abgebildet werden. Die Bogenlänge ist stets Pi/2.

Dabei ist die Teilung der Schnittpunkte auf der x und y Achse nicht proportional! Hat man die Höhe auf 0,5 gedrückt, ist die halbe Sehne bereits auf deutlich mehr als die Hälfte von 1 zu Pi/2 vorgerückt.

Beim Versuch, eine Funktion für die Abhängigkeit zu ermitteln habe ich sehr schnell aufgegeben. Trigonometrische Gleichungen sind nicht immer geschlossen lösbar. Der ermittelte Zusammenhang

cos( Pi / (2*r) ) = 1 - h/r, (r squeeze) um das Zentrum und den Winkel des großen Kreises zu bestimmen, machte wenig Mut.

Vielleicht ist unter den Lesern ein Trigonometrieexperte der das löst oder zeigt: nicht lösbar?
 

Deshalb verfolge ich folgenden Ansatz:

Ich gebe eine fiktive Quetschrate vor und ermittele daraus dann die zugehörigen benötigten Werte:

Aus h = r * ( 1 - cos (alpha / 2 ) ) mit r = (Pi/2) / alpha
kann man die Höhe und dann die anderen Werte ermitteln. Dabei zeigt sich, dass Quetschrate (squeeze) und Höhe etwa "zueinander passen". qSq = 1 - squeeze



Etwas schwieriger als bei den Zylinderkoordinaten in THREEf gestaltet sich auch die Mischung der Funktionen. Der Winkel Theta wird durch die Quetschung verändert, ist aber Argument der Funktionen.

Der noch nicht optimierte aber funktionierende Code:

// ////// only squeeze //////////// ///////////////////////////////////////////////////
qSq = 1 - g.squeeze( t );
alphaSq = qSq * pi2; // squeeze angle
rSq = 1 / qSq; // radius squeeze circle
hSq = pi2 / alphaSq * ( 1 - Math.cos( alphaSq ) ); // height (squeezed)
cSq = rSq - hSq; // center(y)squeeze circle
/////////////////////////////////////////////////////////////////////////////////////////////

function xyzCalculation( south_north ) {

r0 = g.radius;

x0 = r0 * Math.cos( theta ) * Math.cos( phi );
y0 = r0 * Math.sin( thetaY );
z0 = -r0 * Math.cos( theta ) * Math.sin( phi );

r1 = g.radius * g.rPhiTheta( nji, ni, t );
r1y = r1 * ( south_north === SOUTH ? g.stretchSouth( nji, ni, t ) : g.stretchNorth( nji, ni, t ) );

x1 = r1 * Math.cos( theta ) * Math.cos( phi ) + g.radius * g.moveX( nji, ni, t );
y1 = r1y * Math.sin( thetaY ) + g.radius * ( south_north * g.equatorGap( nji, t ) / 2 + g.moveY( nji, ni, t ) );
z1 = - r1 * Math.cos( theta ) * Math.sin( phi ) + g.radius * g.moveZ( nji, ni, t );

dx = x1 - x0;
dy = y1 - y0;
dz = z1 - z0;

//------------

r2 = r0 * rSq;

thetaSq = south_north * ( pi2 - alphaSq ) + alphaSq * theta / pi2 ;
thetaSqY = south_north * ( pi2 - alphaSq ) + alphaSq * thetaY / pi2 ;

x2 = r2 * Math.cos( thetaSq ) * Math.cos( phi );
y2 = r2 * Math.sin( thetaSqY ) - south_north * r0 * cSq;
z2 = - r2 * Math.cos( thetaSq ) * Math.sin( phi );

// ------------

x = x2 + dx;
y = y2 + dy;
z = z2 + dz;

}

Schnappschüsse (Funktion mit t - Zeit):





var parameters = {

equator: 5,
//squeeze: function( t ) { return 0.99}, // bei 1 noch FEHLER 1/0 - Radius UNENDLICH
squeeze: function( t ) { return 0.45 * ( 1 + Math.sin( 0.5 * t ) ) },
rPhiTheta: function ( u, v, t ) { return 0.75 + 2 * (0.5-v)*(0.5-v) + 0.2 * Math.sin( 6.28 * u) },

stretchNorth: function ( u, v, t ) { return 1 + 0.4 * u },

wedges: 5,
usedWedges: 4,

}
 
18.09.2017  
 




HofK
Im obigen Beispiel ist squeeze noch auf den Parameter t beschränkt. Natürlich kommt hier noch der azimutale Winkel hinzu und die Quetschung kann rundherum dosiert werden.
Zwei Schnappschüsse mit einer Dahlie von der IGA in Berlin:





var parameters = {

squeeze: function ( u, t ) { return 0.45 * ( 1 + Math.sin( 6.28 * u ) * Math.sin( t ) ) },

equator: 8,
wedges: 6,
usedWedges: 5,
wedgeOpen: false, // default is true now

}


Da es durch die verschiedenen Funktionen auch Sinn macht bei wedges === usedWedges wedgeOpen zu nutzen, habe ich das inhaltlich geändert.  
 
21.09.2017  
 




HofK
Um die Neuerungen in THREEp.js einfacher testen zu können und um auch diese Sandbox immer halbwegs aktuell zu haben, startet die Box jetzt in der alpha Phase.

Dazu habe ich auf sandbox.threejs.hofk.de/  [...]  eine Auswahlseite hochgeladen.

Von dort kommt man zur "alten" Sandbox THREEf und zur in der Entwicklung befindlichen Box für THREEp.



Der direckte Weg ist

sandboxthreef.threejs.hofk.de/  [...] 

bzw.

sandboxthreep.threejs.hofk.de/  [...] 

Beide Seiten funktionieren nur mit Firefox.

 
23.09.2017  
 




HofK
Nun funktioniert teilweise schon Multimaterial.



Da Material 0 transparent ist, kann man in die Kugel, durch die Kugel hindurch schauen.

Bei 10 Kugelkeilen bzw. Ringen bis zum Äquator werden die Materialien 0 bis 9 genutzt.

In der Sandbox  [...]  kann man das selber ausprobieren (Firefox).

Die Materialspielerei erreicht man wieder durch "passende" Indexrechnungen.

Dabei fallen die Differenzen der Quadrat wie i * i - g.bottomCircle * g.bottomCircle ins Auge. Die Quadrate sind die Summe der faces in einem Keil vom Pol beginnend, 1 + 3 + 5 + 7 ..., also Summe der ungeraden Zahlen. Das Ergebnis ist das Quadrat der Anzahl der Summanden, hier also 4*4 = 16.
if ( g.isBufferGeometry ) {

    if ( !g.materialSouthDefault && g.bottomCircle < eqt ) {

        for ( var i = g.bottomCircle; i < minEqtTop; i ++ ) {

            var jMax = ( 2 * i + 1 ) * uWed;
            fIdx = uWed * ( i * i - g.bottomCircle * g.bottomCircle );

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

                g.groups[ fIdx ].materialIndex =  g.materialSouth( ( j + 0.5 ) / jMax , i / minEqtTop, t );
                fIdx ++;

            }

        }

    }

    if ( !g.materialNorthDefault && g.topCircle > eqt ) {

        for ( var i = topNorth; i < eqt * 2 - Math.max( eqt, g.bottomCircle ); i ++ ) {

            var jMax = ( 2 * i + 1 ) * uWed;
            fIdx = g.faceNorthOffset + uWed * ( i * i - topNorth * topNorth ) ;

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

                g.groups[ fIdx ].materialIndex =  g.materialNorth( ( j + 0.5 ) / jMax, i / ( eqt * 2 - Math.max
                fIdx ++;

            }

        }

    }

}

 
24.09.2017  
 




ByteAttack
Ist echt der Hammer den Du da machst! Wenn es so weiter geht, bekommst Du hier noch deine eigene Wiki...
 
XProfan X3
Website:  [...] 
Facebook:  [...] 
25.09.2017  
 




HofK
Ein fieser Bug hat mich genervt und Zeit gekostet. Er war schon länger drin. Aber nur bei bestimmten Parameterkonstellationen wurde er sichtbar. So konnte er längere Zeit durchschlüpfen.

Es fehlten plötzlich faces! Bei genauerer Betrachtung waren dafür an identischer Position faces doppelt vorhanden.

Da der Code doch schon etwas komplexer ist und die Struktur komplizierter als beim Zylinder, konnte ich den Fehler nicht finden und habe einige mit ähnlichen Fehlern behaftete Varianten produziert .

Der positive Nebeneffekt ist, dass die Funktion vertexNumbersHelper nun auf vertexFaceNumbersHelper erweitert ist. Wahlweise vertices oder faces oder beide Dinge.



Mit dieser Hilfe hatte die Wanze dann keine Chance mehr.

Im Endeffekt war es eine fehlerhafte Zählung in der Schleife für die wedges. Nur wenn Nord- und Südhalbkugel mit geschlossenem Kugelkeil gebildet wurden und der Bodenkreis nicht 0 war, trat der Fehler im südlichen wedge auf und die letzten faces der Nordhalbkugel fehlten. Das Material war dann falsch zugeordnet. Hier eine der produzierten  Fehlleistungen:
falsch



... aber richtig



Sicher noch nicht fehlerfrei - ALPHA - aber zum experimentieren geeignet die aktuelle Version dort:  [...]  (firefox)
 
04.10.2017  
 




HofK
Wer keine Zeit oder Lust hat in der sandbox selber etwas auszuprobieren, kann jetzt da  [...]  schnell Video schauen. Kein abendfüllendes Programm, aber immer auf dem aktuellen Stand. Immer die neuesten Kreationen!
...........................................................................

Jetzt stehe ich vor einer Designentscheidung.
Und die ist schwieriger als vorhin beim Hecke schneiden - rund kurz oder mehr dranlassen. Die Natur wird es sowieso wieder wachsen lasssen. Das Softwaredesign ist da statischer!  

Das Problem:
Die Skalierung des Azimuts (phi) bezieht sich ganz natürlich auf beide Halbkugeln:

endAzimuth,//function ( v, t )// end azimuth angle phi (per theta)
startAzimuth,//function ( v, t )// starting azimuth angle phi (per theta)
scaleAzimuth,//function ( u, t )// scaling between start and end of azimuth angle ( phi 0 .. 2*PI)


Beim Polwinkel ist das nicht so klar. Intern wird jede Halbkugel gesondert vom Pol zum Äquator berechnet. Möchte man jetzt vom Südpol zum Nordpol skalieren, gibt es eine umfangreiche Unterscheidung wie bei der Erstellung der vertices und faces.
Dort ist das kein Problem, da die Sache nur einmal ausgeführt wird. Die Skalierung muss aber ständig in der Funktion xyzCalculation( south_north ) zeitabhängig berechnet werden.

Bei stretch... habe ich mich schon für zwei gesonderte Funktionen für die Halbkugeln entschieden. Der weiter oben abgebildete "Zahn" zeigt, dass es durchaus Sinn macht.

Momentan ist es so, dass die Funktionen identisch auf beide Halbkugeln wirken.

(Zählung für Halbkugeln nih, - für Kugel ni, - Vertices im Kreis i: nji; Äquator ist eqt )
function setVertex( south_north ) {

    vertexType = 1;
    var jMax =  i * uWed + 1;
    nih = i / eqt;//  number i hemisphere | half, 0 pole to 1 equator
    ni = south_north === SOUTH ? nih / 2 : 0.5 + ( 1 - nih ) / 2;//  south pole 0 to north pole 1

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

        nji = j / ( i * uWed );
        xyzCalculation( south_north );
        storeVertex();

    }

}

function xyzCalculation( south_north ) {

    scalingAzimuth = g.startAzimuth( ni, t ) + ( g.endAzimuth( ni, t ) - g.startAzimuth( ni, t ) ) * g.scaleAzimuth( nji, t );
    phi = 2 * Math.PI * uWed / wed * scalingAzimuth + ( vertexType  === 1 ?  phiOffset : 0 );
    // scale:  ni oder nih ????????
    scalingPole =  g.startPole( nji, t ) + ( g.endPole( nji, t ) - g.startPole( nji, t ) ) * g.scalePole( nih, t );
    ...





Gut am Netzwerk erkennbar die Skalierung nach der Wurzelfunktion.
Die Berechnung für Nord -und Südpol und das Zentrum in der Mitte fehlt noch, deshalb nicht korrekt!

Nimmt man zwei getrennte Funktionssätze, muss der Nutzer bei Bedarf diese so "auswählen", dass eine gewünschte einheitliche Skalierung von Süd nach Nord entsteht. Das ist wiederum nachteilig weil etwas schwieriger als mit einem Funktionssatz zu arbeiten.

Ich nehme gern sachdienliche Hinweise entgegen! 

........-----
 
09.10.2017  
 




HofK
Die Skalierung ist fast geschafft.



scalePole: function( v, t ) { return Math.sqrt( v ) },



scalePoleH: function( v, t ) { return Math.sqrt( v ) },

Da ich mich nicht entscheiden konnte, ist ein Kompromiss die beste Lösung.

Man kann eine Funktion scalePoleHemisphere  oder
scalePole angeben. Intern wird mit zwei Funktionen für Süd und Nord gearbeitet. Dabei bedurfte es nicht der befürchteten Unterscheidung wie bei der Erstellung der Geometrie. Eine sinnvolle Umrechnung genügt!



Die Angabe von Funktion scalePole überschreibt eine vorhandene Funktion scalePoleH.
 
13.10.2017  
 




Antworten


Thementitel, max. 100 Zeichen.
 

Systemprofile:

Kein Systemprofil angelegt. [anlegen]

XProfan:

 Beitrag  Schrift  Smilies  ▼ 

Bitte anmelden um einen Beitrag zu verfassen.
 

Themenoptionen

333.467 Betrachtungen

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