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



p.specht

Wird es auch dynamische Objekte (Deckenventilator, Vorhang im Wind, Stubenfliege) geben?
(Ein Narr kann ja mehr fragen, als 10 Weise beantworten...)
 
Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen, zB 'daß' statt 'das'...
01.06.2020  
 




HofK
Vor ca. einem Jahr:

p.specht (17.05.2019)
Na da hab´ ich mit meiner Atomium-Frage ja was angerichtet ...


Wieder netter Versuch mich zu treiben! Erinnert mich an einen geflügelten Spruch meines Vaters, den ich seit Kindheitstagen (seeehr lange her) in Erinnerung habe: "Ein Antreiber ist besser als zehn Arbeiter" 

Aber man muss ja nicht alle Dinge selber machen.

Da ist der Vorhang:  [...] 

Da die Ventilatoren  [...]   [...] 
( müsste man teils das 3D Format umwandeln)

Statt einer Fliege könnte ich meine Hummel anbieten.  [...] 
 
01.06.2020  
 




p.specht

WOW !
 
XProfan 11
Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen, zB 'daß' statt 'das'...
03.06.2020  
 




HofK
Da ich gerade dabei bin Texturen für die Rahmen zu ermöglichen, d.h. die uv Werte zu berechnen, habe ich mal nach fertigen Texturen geschaut. Zumal meine künstlerischen (Wand selbst gemalert!) und fotografischen Fähigkeiten eher begrenzt sind.

Die Software sweethome3d  [...]  bietet Modelle und Texturen zum Download. Lizenz beachten!

Etwas Buche für die 3D-Fensterbank, eine Türimitation (Textur, nicht 3D!) und eine Treppe (3D .obj Datei mit .mtl), die noch etwas sinnlos im Raum steht, machen den Raum etwas "gemütlicher". Da kann man sich bei Bedarf richtig austoben!

 
05.06.2020  
 




HofK
Mit den Texturen für die Rahmen dauert es jetzt etwas länger. Man sollte angefangene Arbeiten nicht mehr als ein Jahr liegen lassen. Zumal, wenn man die Ansätze/Herleitungen so salopp wie ich macht. Konnte gerade noch einen A5-Zettel aus dem Stapel fischen, auf dem einige Winkel, Strecken und Formeln stehen. Wenn man das nicht selbst in Form einer ordentlichen Anleitung für andere Personen schreibt, sieht man selbst nach einiger Zeit nicht mehr sofort klar. Auch meine Programm-Kommentare sind eher sehr knapp.

Man staunt, was man da erdacht hat und lernt es fast wie neu.

Aber ich bin optimistisch. Das ist zwar noch nicht korrekt, aber ein Anfang.



Man muss mit Hilfe der Winkel Seiten der im Bild erkennbaren Dreiecke (nicht ordentlich in der Textur) berechnen und dann im Verhältnis zur längsten Seite die entsprechenden Abschläge für den u-Wert an allen vier Ecken machen.

Der v-Wert ist sehr einfach nur 0 bzw. 1, da die Profile stets parallele Kanten haben.

Für das erste und letzte Segment braucht es eine extra Fallunterscheidung.
 
08.06.2020  
 




HofK
HofK (08.06.2020)
Für das erste und letzte Segment braucht es eine extra Fallunterscheidung.


Es ist einfacher als angenommen, eine Fallunterscheidung ist dafür nicht nötig. Es gibt insgesamt nur vier Fälle. Die Berechnung selbst ist auch recht elementar. Ich hatte anfangs wieder mal viel zu kompliziert gedacht.

Die Lösung beruht auf der Berechnung der Projektion eines Vektors auf einen anderen Vektor. Interaktiv kann man das z.B. dort ausprobieren. [...] 

Man speichert die vier Eckpunkte 1.. 4 und berechnet dann die Länge des Vektors v14. Die über ein Rechteck hinausgehenden bzw. fehlenden Strecken sind gerade die Projektion, die man mit dem Skalarprodukt ( Punktprodukt / dot product ) und dieser Länge errechnet.


frmpos[ j ].push( x1, y1, z1, x2, y2, z2, x4, y4, z4, x2, y2, z2, x3, y3, z3, x4, y4, z4 );// positions
a = len( x4 - x1, y4 - y1, z4 - z1 );// length v14
d2 = dot( x4 - x1, y4 - y1, z4 - z1, x2 - x1, y2 - y1, z2 - z1 ) / a;
d3 = dot( x1 - x4, y1 - y4, z1 - z4, x3 - x4, y3 - y4, z3 - z4, ) / a;

if ( d2 >= 0 && d3 >= 0 ) {

    u1 = 0;
    u2 = d2 / a;
    u3 = 1 - d3 / a;
    u4 = 1;

}

if ( d2 >= 0 && d3 < 0 ) {

    u1 = 0;
    u2 = d2 / ( a - d3 );
    u3 = 1;
    u4 = 1 + d3 / ( a - d3 );

}

if ( d2 < 0 && d3 < 0 ) {

    u1 = -d2 / ( a - d2 - d3 );
    u2 = 0;
    u3 = 1;
    u4 = 1 + d3 / ( a - d2 - d3  );

}

if ( d2 < 0 && d3 >= 0 ) {

    u1 = -d2 / ( a - d2  );
    u2 = 0;
    u3 = 1 - d3 / ( a - d2  );
    u4 = 1;

}

frmuvs[ j ].push( u1, 1, u2, 0, u4, 1, u2, 0, u3, 0, u4, 1 );// uv's'
 
11.06.2020  
 




p.specht

Meister!
 
XProfan 11
Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen, zB 'daß' statt 'das'...
12.06.2020  
 




HofK
Ich habe die Sache mal auf meine ältere Variante
ProfiledContourGeometry MultiMaterial  [...]   [...]  übertragen.

Dabei sind diverse Änderungen in der Struktur der Geometrie nötig.



Dort probieren [...] 

(Update: Es gab einen Tippfehler im Link. Ordner ...GeometrUVs ohne y)
<!DOCTYPE html>
<!-- https://discourse.threejs.org/t/profiledcontourgeometry-multimaterial/5801 -->
<head>
<title> ProfiledContourGeometryUVs  </title>
<meta charset="utf-8" />
<style>

body {

    margin: 0;

}

</style>
</head>
<body> </body>
<script src="../js/three.min.117.js"></script>
<script src="../js/OrbitControls.117.js"></script>
<script>
'use strict'
// @author hofk
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.set( -6, 18, 20 );
const renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const controls = new THREE.OrbitControls( camera, renderer.domElement );
const light = new THREE.DirectionalLight( 0xffffff, 0.6);
light.position.setScalar( 10 );
scene.add( light );
scene.add(new THREE.AmbientLight( 0xffffff, 0.8));
const helper = new THREE.GridHelper( 20, 20);
scene.add( helper );
const detail = 5;
let profileShape1 = [];

for ( let i = detail; i > -1; i --){

    profileShape1.push ( 1.8 * Math.cos( i / detail * Math.PI * 2 ), 1.8 * Math.sin( i / detail * Math.PI * 2 ) );

}

const contour1 = [
-3,  4,
0,  4,// here only to show that angle of 180° horizontal works
4,  4,
2,  1,
4, -2,
0, -3,
-4, -3,
-4,  0
];
const profileShape2 = [ -1,1, 1,1, 1,-1, -1,-1 ];
const contour2 = [
2,-2,
2, 0,
4, 4,
9, 4,
9, 2,// here only to show that angle of 180° vertikal works
9, 0,
];
const  tex1 = new THREE.TextureLoader().load('uvgrid01.png' );
const  tex2 = new THREE.TextureLoader().load('beech.jpg' ); // License: free, Non-commercial use
const  tex3 = new THREE.TextureLoader().load('pngwing-com-water.png' );// License:  free, Non-commercial use
//const m0 = new THREE.MeshPhongMaterial( { color: 0xfa0001, side: THREE.DoubleSide } );
//const m1 = new THREE.MeshPhongMaterial( { color: 0xff7b00, side: THREE.DoubleSide } );
//const m2 = new THREE.MeshPhongMaterial( { color: 0xf9f901, side: THREE.DoubleSide } );
const m0 = new THREE.MeshPhongMaterial( { map: tex3, side: THREE.DoubleSide } );
const m1 = new THREE.MeshPhongMaterial( { map: tex2, side: THREE.DoubleSide } );
const m2 = new THREE.MeshPhongMaterial( { map: tex1, side: THREE.DoubleSide } );
const m3 = new THREE.MeshPhongMaterial( { color: 0x008601, side: THREE.DoubleSide } );
const m4 = new THREE.MeshPhongMaterial( { color: 0x01bbbb, side: THREE.DoubleSide } );
const m5 = new THREE.MeshPhongMaterial( { color: 0x250290, side: THREE.DoubleSide } );
//const m3 = new THREE.MeshPhongMaterial( { map: tex1, side: THREE.DoubleSide } );
//const m4 = new THREE.MeshPhongMaterial( { map: tex1, side: THREE.DoubleSide } );
//const m5 = new THREE.MeshPhongMaterial( { map: tex1, side: THREE.DoubleSide } );
const m6 = new THREE.MeshPhongMaterial( { color: 0xfc4ea5, side: THREE.DoubleSide } );
const m7 = new THREE.MeshPhongMaterial( { color: 0x83058a, side: THREE.DoubleSide } );
const m8 = new THREE.MeshPhongMaterial( { color: 0x83058a, side: THREE.DoubleSide } );
const materials = [ m0, m1, m2, m3, m4, m5, m6, m7, m8, m0, m1, m2, m3, m4, m5, m6, m7, m8, m0, m1, m2, m3, m4, m5, m6, m7, m8, m0, m1, m2, m3, m4, m5, m6, m7, m8, m0, m1, m2, m3, m4, m5, m6, m7, m8, m0, m1, m2, m3, m4, m5, m6, m7, m8, m0, m1, m2, m3, m4, m5, m6, m7, m8, m0, m1, m2, m3, m4, m5, m6, m7, m8, m0, m1, m2, m3, m4, m5, m6, m7, m8 ];
//............................................................ matPerSquare, contourClosed
const frame1 = ProfiledContourUV( profileShape1, contour1, materials, false , true );
scene.add( frame1 );
frame1.position.x = -5;
frame1.position.z = 3;
frame1.rotation.y = 2.8;
const frame2 = ProfiledContourUV( profileShape2, contour2, materials, true, false );
frame2.position.z = -4;
scene.add( frame2 );
render();

function render() {

    requestAnimationFrame(render);
    renderer.render(scene, camera);

}

function ProfiledContourUV( profileShape, contour, materials, matPerSquare, contourClosed ) {

    // creates group of frame strips, non indexed BufferGeometry
    const len = ( x, y, z ) => Math.sqrt( x * x + y * y + z * z );
    const dot = (x1, y1, z1, x2, y2, z2) => ( x1 * x2 + y1 * y2 + z1 * z2 );
    matPerSquare = matPerSquare!== undefined ? matPerSquare : false;
    contourClosed = contourClosed !== undefined ? contourClosed : true;
    if( contourClosed ) contour.push( contour[ 0 ], contour[ 1 ] );
    const hs1 = contour.length / 2;
    const rs1 = profileShape.length / 2;
    const hs = hs1 - 1;// height segments
    const rs = rs1 - 1;// radius segments
    let	vtx = [];// rs1 many vertex colums
    let	frmpos = [];// hs many geometries and meshes
    let	frmuvs = [];// hs many uv's'

    for ( let j = 0; j < rs; j ++ ) {

        vtx.push( [] );
        frmpos.push( [] );
        frmuvs.push( [] );

    }

    vtx.push( [] );// last colum
    let gFrame = [];// geometries of frame strips
    let frame = [];// meshes of frame strips
    const fGroup = new THREE.Group( );
    let i1, i2, i3, i6, j1, j3;
    let xc0, yc0, xc1, yc1, xc2, yc2, xSh, xDiv;
    let dx, dy, dx0, dy0, dx2, dy2;
    let e0x, e0y,e0Length, e2x, e2y, e2Length, ex, ey, eLength;
    let xd, phi, bend;
    let x, y, z, x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4;
    let a, u1, u2, u3, u4, d2, d3;
    const epsilon = 0.000001;

    for ( let j = 0; j < rs1; j ++ ) {

        for ( let i = 0; i < hs1; i ++ ) {

            i2 = 2 * i;
            xc1 = contour[ i2 ];
            yc1 = contour[ i2 + 1 ];

            if ( i === 0 ) {

                xc0 = contour[ ( hs - 1 ) * 2 ];// penultimate point
                yc0 = contour[ ( hs - 1 ) * 2 + 1 ];

            } else {

                xc0 = contour[ i2 - 2 ];// previous point
                yc0 = contour[ i2 - 1 ];

            }

            if ( i === hs ) {

                xc2 = contour[ 2 ];// second point
                yc2 = contour[ 3 ];

            } else {

                xc2 = contour[ i2 + 2 ];// next point
                yc2 = contour[ i2 + 3 ];

            }

            if ( !contourClosed ) {

                if ( i === 0 ) {

                    // direction
                    dx2 = xc2 - xc1;
                    dy2 = yc2 - yc1;
                    // unit vector
                    e2Length = Math.sqrt( dx2 * dx2 + dy2 * dy2 );
                    e2x = dx2 / e2Length;
                    e2y = dy2 / e2Length;
                    // orthogonal
                    ex = e2y;
                    ey = -e2x;

                }

                if ( i === hs ) {

                    // direction
                    dx0 = xc1 - xc0;
                    dy0 = yc1 - yc0;
                    // unit vector
                    e0Length = Math.sqrt( dx0 * dx0 + dy0 * dy0 );
                    e0x = dx0 / e0Length;
                    e0y = dy0 / e0Length;
                    // orthogonal
                    ex = e0y;
                    ey = -e0x;

                }

                xDiv = 1;
                bend = 1;

            }

            if ( ( i > 0 && i < hs ) || contourClosed ) {

                // directions
                dx0 = xc0 - xc1;
                dy0 = yc0 - yc1;
                dx2 = xc2 - xc1;
                dy2 = yc2 - yc1;

                if( Math.abs( ( dy2 / dx2 ) - ( dy0 / dx0 ) ) < epsilon ) {// prevent 0

                    dy0 += epsilon;

                }

                if( Math.abs( ( dx2 / dy2 ) - ( dx0 / dy0 ) ) < epsilon ) {// prevent 0

                    dx0 += epsilon;

                }

                // unit vectors
                e0Length = Math.sqrt( dx0 * dx0 + dy0 * dy0 );
                e0x = dx0 / e0Length;
                e0y = dy0 / e0Length;
                e2Length = Math.sqrt( dx2 * dx2 + dy2 * dy2 );
                e2x = dx2 / e2Length;
                e2y = dy2 / e2Length;
                // direction transformed
                ex = e0x + e2x;
                ey = e0y + e2y;
                eLength = Math.sqrt( ex * ex + ey * ey );
                ex = ex / eLength;
                ey = ey / eLength;
                phi = Math.acos( e2x * e0x + e2y * e0y ) / 2;
                bend = Math.sign( dx0 * dy2 - dy0 * dx2 );// z cross -> curve bending
                xDiv = Math.sin( phi );

            }

            xSh = profileShape[ j * 2 ];
            xd = xSh / xDiv;
            dx = xd * bend * ex;
            dy = xd * bend * ey;
            x = xc1 + dx;
            y = yc1 + dy;
            z = profileShape[ j * 2 + 1 ];// ySh
            vtx[ j ].push( x, y, z );// store vertex
            //dApex = xd * Math.cos( phi );

        }

    }

    for ( let j = 0; j < rs; j ++ ) {

        j1 = j + 1;
        j3 = 3 * j;

        for ( let i = 0; i < hs; i ++ ) {

            i3 = 3 * i;
            i6 = i3 + 3;
            x1 = vtx[ j ][ i3 ];
            y1 = vtx[ j ][ i3 + 1 ];
            z1 = vtx[ j ][ i3 + 2 ] ;
            x2 = vtx[ j1 ][ i3 ];
            y2 = vtx[ j1 ][ i3 + 1 ];
            z2 = vtx[ j1 ][ i3 + 2 ];
            x3 = vtx[ j1 ][ i6 ];
            y3 = vtx[ j1 ][ i6 + 1 ];
            z3 = vtx[ j1 ][ i6 + 2 ];
            x4 = vtx[ j ][ i6 ];
            y4 = vtx[ j ][ i6 + 1 ];
            z4 = vtx[ j ][ i6 + 2 ];
            frmpos[ j ].push( x1, y1, z1, x2, y2, z2, x4, y4, z4, x2, y2, z2, x3, y3, z3, x4, y4, z4 );
            a = len( x4 - x1, y4 - y1, z4 - z1 );
            d2 = dot( x4 - x1, y4 - y1, z4 - z1, x2 - x1, y2 - y1, z2 - z1 ) / a;
            d3 = dot( x1 - x4, y1 - y4, z1 - z4, x3 - x4, y3 - y4, z3 - z4, ) / a;

            if ( d2 >= 0 && d3 >= 0 ) {

                u1 = 0;
                u2 = d2 / a;
                u3 = 1 - d3 / a;
                u4 = 1;

            }

            if ( d2 >= 0 && d3 < 0 ) {

                u1 = 0;
                u2 = d2 / ( a - d3 );
                u3 = 1;
                u4 = 1 + d3 / ( a - d3 );

            }

            if ( d2 < 0 && d3 < 0 ) {

                u1 = -d2 / ( a - d2 - d3 );
                u2 = 0;
                u3 = 1;
                u4 = 1 + d3 / ( a - d2 - d3  );

            }

            if ( d2 < 0 && d3 >= 0 ) {

                u1 = -d2 / ( a - d2  );
                u2 = 0;
                u3 = 1 - d3 / ( a - d2  );
                u4 = 1;

            }

            frmuvs[ j ].push( u1, 1, u2, 0, u4, 1, u2, 0, u3, 0, u4, 1 );

        }

    }

    for ( let j = 0; j < rs; j ++ ) {

        gFrame[ j ] = new THREE.BufferGeometry( );
        gFrame[ j ].setAttribute('position', new THREE.BufferAttribute( new Float32Array( frmpos[ j ] ), 3 ) );
        gFrame[ j ].setAttribute('uv', new THREE.BufferAttribute( new Float32Array( frmuvs[ j ] ), 2 ) );

        if ( matPerSquare ) {// MultiMaterial support (for each square)

            for ( let i = 0; i < hs; i ++ ) {

                gFrame[ j ].addGroup( i * 6, 6, j * hs + i );

            }

            frame[ j ] = new THREE.Mesh( gFrame[ j ], materials );

        } else {// material per frame strip

            frame[ j ] = new THREE.Mesh( gFrame[ j ], materials[ j ] );

        }

        gFrame[ j ].computeVertexNormals( );
        fGroup.add( frame[ j ] )

    }

    return fGroup;// group of frame strips

}

</script>
</html>
 
15.06.2020  
 




HofK
Nun ist auch eine Version im Addon THREEg verfügbar. [...] 

Abweichend von den sonstigen Beispielen wird hier nicht nur die Geometrie erzeugt, sondern daraus in zwei Varianten für die Anordnung der Materialien eine Gruppe von Meshes erzeugt. Diese wird mit scene.add( ); der Anwendung hinzugefügt.
const frame = new THREE.Group( );
frame.createProfiledContourUV = THREEg.createProfiledContourUV;
// ......................................................... matPerSquare, contourClosed
frame.createProfiledContourUV( profileShape, contour, materials, false , true );
scene.add( frame );

In der obigen Variante mit der eigenständigen Funktion wird die Definition der Gruppe innerhalb der Funktion erledigt.
 
16.06.2020  
 




p.specht

Schaffen ältere Computer das? Langsam wird die Sache vielleicht zu abhängig vom Einsatz teurer Grafikkarten...
 
XProfan 11
Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen, zB 'daß' statt 'das'...
17.06.2020  
 




HofK
p.specht (17.06.2020)
... ältere Computer ... zu abhängig vom Einsatz teurer Grafikkarten...


Das ist immer relativ. Die Sachen, die ich hier mache, laufen wenn es um bewegte Grafik geht zwar nicht mehr auf meinem alten Android 4.4 Tablet von 2014, aber sehr wohl auf meinem Mittelklasse Smartphone von 2017. Bei "richtigen" Computern ist die Sache entspannter. Mein leicht defektes Notebook etwas gehobener Ausstattung (siehe weiter oben) aus dem Produktionsjahr 2012 hat keine Probleme. Wenn man allerdings aufwändige Grafikspiele im Sinn hat, sollte es etwas neueres und teures sein - Gaming PC mit "ordentlich teurer" Grafikkarte!

Tablets mit Android 4.4 sind bei vielen Dingen bereits außen vor. Selbst die Öffentlich Rechtlichen für die wir alle zwangsweise "blechen" meinen, soetwas nicht mehr unterstützen zu müssen. Dabei haben sich die meisten Filme selbst nicht geändert (ich meine kein 4K u.ä.) und sind von der Technik problemlos beherrschbar. Aber es macht Aufwand, für verschiedene Android Versionen zu programmieren. Habe das selbst vor 6 Jahren getestet.
 
18.06.2020  
 




Jörg
Sellmeyer
Ließen sich diese Algorithmen eigentlich auch irgendwie nach Profan übertragen?
Ich staune immer wieder, wenn ich diesen Thread aufpoppen sehe und denke: Wow - wenn ich nur wüßte, wie und wo ich das mal einsetzen könnte.
In Profan jedenfalls eher mal als in PHP/Javaskript.
 
XProfan X4
Windows XP SP2 XProfan X4
... und hier mal was ganz anderes als Profan ...
19.06.2020  
 




Antworten


Thementitel, max. 100 Zeichen.
 

Systemprofile:

Kein Systemprofil angelegt. [anlegen]

XProfan:

 Beitrag  Schrift  Smilies  ▼ 

Bitte anmelden um einen Beitrag zu verfassen.
 

Themenoptionen

333.492 Betrachtungen

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