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



HofK
Jörg Sellmeyer (19.06.2020)
Ließen sich diese Algorithmen eigentlich auch irgendwie nach Profan übertragen?


Vor knapp 10 Jahren habe ich mit XProfan 11 einige Tests auf der Basis von OpenGL gemacht. In der Hilfe zu XProfan 11 gibt es dazu Kapitel.
Ich wollte sehen, was das ist. Weit vor der Zeit als ich auf three.js gestoßen bin.

Dieses Framework baut auf WebGL auf. Zwischen OpenGL und WebGL gibt es natürlich einige Unterschiede.

Betrachtet man meine Programme die hauptsächlich 3D Geometrie bearbeiten, so sind die eigentlichen Algorithmen unabhängig von einer speziellen Programmiersprache und einem bestimmten Framework. Anders sieht es mit dem ganzen Drumherum wie Licht, Bewegung usw. aus.

Immer wenn = new THREE. auftaucht, benutze ich fertig konfigurierte Dinge aus three.js. Beispielsweise auch mal = new THREE.Vector3()

Da ich aber z.B. in der Vektorrechnung lieber komponentenweise selbst programmiere, ist das in meinen Programmen selten. Das hat Vor- und Nachteile. Mit new... hat man mehr Objekte und verbraucht Ressourcen, der Code wird eventuell kürzer. Jeder hat seine Vorlieben.

Vorteil:
Die komponentenweise Rechnung ist problemlos auf beliebige Sprachen übertragbar. Nur Änderungen in der konkreten Syntax.


Ein gutes Beispiel ist die Triangulation impliziter Flächen. Siehe weiter oben. Das Original war in Pascal programmiert, die Anzeige erfolgte mit povray.

Allerdings habe ich da zusätzlich die Struktur des Algorithmus und damit des Programms komplett überarbeitet.

Einfach mal mit dem verfügbaren XProfan an einem zunächst einfachen Beispiel testen, wie das geht.

Gerade wiedergefunden:



Rotiert natürlich schön.
 
26.06.2020  
 




HofK
In den letzten Wochen blieb wegen anderer, wichtigerer Dinge kaum Zeit für three.js. Habe es gerade so geschafft, das Forum discourse.threejs.org  [...]  zu verfolgen und die Beispiele zu sammeln, zu bearbeiten und hochzuladen.

Da gibt es eine ganze Reihe neuer und interessanter Dinge. Einfach mal in die Sammlung bei 2020 schauen.  [...] 

 [...] 
 
26.08.2020  
 




HofK
In den Beispielen von discourse.threejs.org wird seit 2020 von der Variante mit ES6 Modulen Gebrauch gemacht. Diese Beispiele lassen sich wegen der Sicherheitsrichtlinien nicht lokal im Browser aufrufen. Deshalb habe ich den Punkt
"Local use of the examples" neu verfasst.



Für Windows 10 (nur das kann ich testen) habe ich eine sehr anfängerfreundliche Variante gefunden. Der lokale Server Apache kommt ohne Installation aus.

Die Anleitung in Englisch siehe unter  [...] 

Sollte jemand eine entsprechend einfache Variante (mit Apache?) für andere Betriebssysteme testen und kurz beschreiben, kann ich das hinzufügen.
 
________________________________________________________________

Lokale Nutzung der Beispiele

Die Modulversion three.js erfordert unbedingt einen lokalen Server.
Ab 2020 sind bereits viele Beispiele in dieser Form erstellt worden.
Ende des Jahres werden sie als zip-Datei zum Download zur Verfügung stehen.

Eine besonders einfache Variante bietet der lokale Server Apache.
Er ist auch im XAMPP-Paket enthalten.

Solo benötigt er keine Installation (nur unter Windows 10 getestet).

Rufen Sie die Seite  [...]  auf.

Laden Sie z.B. httpd-2.4.46-win64-VS16.zip herunter (verwenden Sie die aktuelle Version 64/32 bit)

Entpacken Sie die Datei und kopieren Sie den Ordner Apache24 nach C:\

Abhängig von der bereits auf dem Computer installierten Software können Dateien fehlen und es kann eine Meldung erscheinen. Da Apache in C++ geschrieben ist, benötigt das Programm eine entsprechende Laufzeitumgebung unter Windows. Diese wird von der Compiler-Software Visual C++ zur Verfügung gestellt und ist oft bereits von anderer Software installiert. Es handelt sich um die Datei VCRUNTIME140.dll, sie muss vorhanden sein.

Um den lokalen Server zu starten, führen Sie die Datei C:\Apache24\bin\httpd.exe aus.
Das sich öffnende Fenster kann minimiert werden.

Wenn Sie den Standardordner \Apache24\htdocs für die Beispiele ändern möchten, müssen Sie die Datei httpd.conf im Ordner \Apache24\conf editieren.

Die Zeilen

DocumentRoot "${SRVROOT}/htdocs"
<Directory "${SRVROOT}/htdocs">

ändern Sie auf z.B.

DocumentRoot "D:\collection"
<Directory "D:\collection">

Danach Apache neu starten!

Geben Sie 127.0.0.1 oder localhost in den Browser ein und es wird der Index des Ordners oder die Webseite angezeigt, falls eine index.html vorhanden ist. Da die Beispiele der Sammlung in den Ordnern nicht als index.html, sondern mit ihrem Namen gespeichert sind, müssen Sie diese im Index des Ordners anklicken.

Ein Beispiel aus dem Jahr 2019

 
08.09.2020  
 




HofK
Endlich mal wieder etwas Zeit gefunden um zu programmieren. Da wo ich Ende Juni aufgehört habe geht es weiter. Es fehlte noch die Möglichkeit auch die Kappen mit einer Textur zu versehen. Dazu habe ich ein Update erstellt.

Siehe  [...] 
und  [...] 


<!DOCTYPE html>
<!-- https://discourse.threejs.org/t/profiledcontourgeometry-multimaterial/5801/2 -->
<head>
<title> ProfiledContourGeometryUVs  </title>
<meta charset="utf-8" />
<style>

body {

    margin: 0;

}

</style>
</head>
<body> </body>
<script src="../js/three.min.120.js"></script>
<script src="../js/OrbitControls.120.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.75 * Math.cos( 0.7 + i / detail * Math.PI * 2 ), 1.75 * Math.sin( 0.7 + 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.77,1, 1,-1, -1.4,-1.99 ];
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: tex1, side: THREE.DoubleSide } );
const m1 = new THREE.MeshPhongMaterial( { map: tex2, side: THREE.DoubleSide } );
const m2 = new THREE.MeshPhongMaterial( { map: tex3, 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: tex3, side: THREE.DoubleSide } );
const m5 = new THREE.MeshPhongMaterial( { map: tex2, 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 m6 = new THREE.MeshPhongMaterial( { map: tex1, side: THREE.DoubleSide } );
const m7 = new THREE.MeshPhongMaterial( { map: tex2, side: THREE.DoubleSide } );
const m8 = new THREE.MeshPhongMaterial( { map: tex3, 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, openEnded );
const frame1 = ProfiledContourUV( profileShape1, contour1, materials, false , false, false );
scene.add( frame1 );
frame1.position.x = -5;
frame1.position.z = 3;
frame1.rotation.y = 2.8;
const frame2 = ProfiledContourUV( profileShape2, contour2, materials, true, false, false );
frame2.position.z = -4;
scene.add( frame2 );
render();

function render() {

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

}

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

    // 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;
    openEnded = openEnded  !== undefined ? ( contourClosed === true ? true : openEnded ) : 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

    if(  !openEnded ) {// for two ends

        frmpos.push( [], [] );// for two ends
        frmuvs.push( [], []  );

    }

    let gFrame = [];// geometries of frame strips
    let frame = [];// meshes of frame strips
    const fGroup = new THREE.Group( );
    let i1, i2, i3, i6, j1, j2;
    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 x1L, y1L, x2L, y2L, xMin, yMin, xMax, yMax;
    let a, u1, u1a, u1b, u2, u3, u4, v1, v2, v3, d2, d3;
    const epsilon = 0.000001;
    xMin = Infinity;
    yMin = Infinity;
    xMax = -Infinity;
    yMax = -Infinity;

    if( !openEnded ) {

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

            j2 = 2 * j;

            if ( profileShape[ j2 ] < xMin ) xMin = profileShape[ j2 ];

                if ( profileShape[ j2 + 1 ] < yMin ) yMin = profileShape[ j2 + 1 ];

                    if ( profileShape[ j2 ] > xMax ) xMax = profileShape[ j2 ];

                        if ( profileShape[ j2 + 1 ] > yMax ) yMax = profileShape[ j2 + 1 ];

                        }

                    }

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

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

                            if( j === 0 && i === hs && !openEnded ) {//center

                                x1L = xc1;
                                y1L = yc1;

                            }

                            if( j === 0 && i === 0 && !openEnded ) {//center

                                x2L = xc1;
                                y2L = yc1;

                            }

                        }

                    }

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

                        j1 = j + 1;

                        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 );

                        }

                    }

                    if( !openEnded ) {

                        dx = xMax - xMin;
                        dy = yMax - yMin;
                        v1 = -yMin / dy;
                        u1a = -xMin / dx;
                        u1b = 1 - u1a;
                        i3 = 3 * hs;

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

                            j1 = j + 1;
                            j2 = 2 * j;
                            x1 = vtx[ j ][ 0 ];
                            y1 = vtx[ j ][ 1 ];
                            z1 = vtx[ j ][ 2 ];
                            x2 = vtx[ j1 ][ 0 ];
                            y2 = vtx[ j1 ][ 1 ];
                            z2 = vtx[ j1 ][ 2 ];
                            frmpos[ rs ].push( x2L, y2L, 0, x1, y1, z1, x2, y2, z2 );
                            u2 = ( profileShape[ j2 ] - xMin ) / dx;
                            v2 = ( profileShape[ j2 + 1 ] - yMin ) / dy;
                            u3 = ( profileShape[ j2 + 2 ] - xMin ) / dx;
                            v3 = ( profileShape[ j2 + 3 ] - yMin ) / dy;
                            frmuvs[ rs ].push( u1a, v1, u2, v2, u3, v3 );
                            x1 = vtx[ j1 ][ i3 ];
                            y1 = vtx[ j1 ][ i3 + 1 ];
                            z1 = vtx[ j1 ][ i3 + 2 ] ;
                            x2 = vtx[ j ][ i3 ];
                            y2 = vtx[ j ][ i3 + 1 ];
                            z2 = vtx[ j ][ i3 + 2 ];
                            frmpos[ rs1 ].push( x1L, y1L, 0, x1, y1, z1, x2, y2, z2 );
                            u2 = 1 - ( profileShape[ j2 + 2 ] - xMin ) / dx;
                            v2 = ( profileShape[ j2 + 3 ] - yMin ) / dy;
                            u3 = 1 - ( profileShape[ j2 ] - xMin ) / dx;
                            v3 = ( profileShape[ j2 + 1 ] - yMin ) / dy;
                            frmuvs[ rs1 ].push( u1b, v1, u2, v2, u3, v3 );

                        }

                    }

                    for ( let j = 0; j < ( openEnded ? rs : rs + 2 ); 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>
 
18.09.2020  
 




HofK
Auch die Version im Addon THREEg.js wurde geupdated und beherrscht die Deckel mit Textur.  [...] 
 
20.09.2020  
 




p.specht

Perfekt! Bald kommt ein Angebot von Google oder AutoCAD. Deren Strategie ist ja das Aufkaufen potentieller Konkurrenten
 
XProfan 11
Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen, zB 'daß' statt 'das'...
20.09.2020  
 




HofK
Habe endlich etwas mehr Zeit gefunden um den Schauraum umzuprogrammieren. Die Bewegung war ja etwas ruckelig. Siehe [...]  und  [...] 

Der neue Ansatz besteht darin, vollständig auf groups zu verzichten und stattdessen für jedes benutzte Material eine eigene Geometrie und ein eigenes mesh zu erzeugen. Das ist nur sinnvoll, wenn die Bauteile nach der Erzeugung unbeweglich sind. Das ist bei den Böden, Decken, Wänden, Rahmen usw. eines Schauraums gegeben.

Mittels .push werden arrays für die Vertices und uv's gefüllt.
let vt = [];// vertices
let uv = [];

for ( let i = 0; i < m.length; i ++ ) {

    m[ i ].unshift( i )// insert index at the front of the material definition, used for vt, uv  index
    vt.push( [] );//  vertices array for each material
    uv.push( [] );//  uv's array for each material

}


Bei der Erzeugung der einzelnen Komponenten werden diese je nach Material zerlegt. Dazu wird der Materialindex bestimmt.

Beispiel
vt[ getMatIndex( cp, i, mi, mNo ) ].push( x1,y1,z1, x2,y2,z2, x3,y3,z3, x1,y1,z1, x3,y3,z3, x4,y4,z4 );
uv[ getMatIndex( cp, i, mi, mNo ) ].push( u1, v1, u2, v2, u3, v3, u1, v1, u3, v3, u4, v4 );

Die fertig definierten Geometrien und Meshes werden dann in einer Schleife erzeugt.
let geometries = [];
let meshes = [];

for ( let i = 0; i < m.length; i ++ ) {

    if ( vt[ i ].length > 0 ) {// only for defined materials, not for material Empty

        geometries[ i ] = new THREE.BufferGeometry();
        geometries[ i ].setAttribute('position', new THREE.BufferAttribute( new Float32Array( vt[ i ] ), 3 ) );
        geometries[ i ].setAttribute('uv', new THREE.BufferAttribute( new Float32Array( uv[ i ] ), 2 ) );
        geometries[ i ].computeVertexNormals();
        meshes[ i ] = new THREE.Mesh( geometries[ i ], getMaterial( m[ i ] ) );
        scene.add( meshes[ i ] );

    } else {

        geometries[ i ] = null;
        meshes[ i ]  = null;

    }

}


Der Aufwand hat sich offenbar gelohnt, es läuft bei jetzt wesentlich mehr Elementen und mehr Materialien im Schauraum deutlich besser.

renderer.info.render ergibt maximale Werte, wenn im Spiegel Gltf/Obj Modelle dargestellt werden.
calls: 45, triangles ca. 42000, points: 0, lines: 84

Leider kann ich es mir wegen meines sehr begrenzten Überblicks über die interne Arbeitsweise von three.js/ WebGL nicht erklären, aber offensichtlich hat es wie nur vermutet doch etwas mit der Gliederung in Gruppen zu tun. Denn die Anzahl der Materialien habe ich etwas erweitert, gegenwärtig 21 Materialien. Also habe ich 21 meshes mit je einem Material.

Am Schauraum selbst sind noch einige Feinheiten zu erledigen.

Ein Ausschnitt.

 
15.10.2020  
 




HofK
Schauraum - BETA

Schauräume einfach zu generieren aus Daten einer Bauzeichnung oder Maßskizze.

Man findet eine ganze Reihe von Tools zur Darstellung von Gebäuden und Räumen nebst Einrichtung. Darunter sowohl fest definierte als auch interaktiv zu gestaltende.

Der Grundlage für die Gestaltung von flexibel zu konfigurierenden Räumen ist in diesem Fall eine Bauzeichnung oder eine einfache Maßskizze.

Die Daten werden in kompakter Form in eine einfache Textdatei (.js ) nach einem vorgegebenen Schema geschrieben. Für optionale Werte kann man die Defaults selbst festlegen. Nach jedem Neueintrag sieht man nach Aktualisierung der Seite sofort das Ergebnis. Bei einer fehlerhaften Eingabe kann man so unmittelbar reagieren.

Andererseits kann man einfach zwei Schrägstriche // vor eine Zeile setzen und auf diese Weise Elemente temporär entfernen.

Die kompakte Form der Daten erfordert anfangs erhöhte Konzentration bei der Eingabe. Nach ein wenig Übung kann man dann aber sehr schnell verschiedene Szenarien durchspielen.

Mit der Angabe weniger Daten werden auch Beleuchtung, Spiegel und 3D Modelle integriert. Mit der Festlegung von Farben und der Zuordnung von Materialien und Multi-Materialien lassen sich die Räume individuell gestalten.

Siehe Beschreibung showroomDesignDE.pdf Herunterladen
und Beispieldateien
showroomDesign.js Herunterladen

materials.js Herunterladen
zu den Bildern

Das Programm ist modular strukturiert und kann bei Bedarf problemlos um weitere Elemente und Effekte ergänzt werden. Die meisten Dinge sind als selbst definierte nicht indizierte Puffer-Geometrie (non indexed BufferGeometry) realisiert.

Bisher sind folgende Dinge verfügbar:
Beleuchtung, Böden und Decken (mit individuellem Niveau auch Rampen und Dachschrägen), Wände mit Öffnungen (extra Materialien) und Leibungen, Torbögen, runde Wände, Bauteile mit variabler Mantelfunktion, Spiegel, Rahmen (mit ConstructFrameShowroom.html, einer angepassten Vaiante von ConstructFrame.html, siehe  [...]  zu generieren), Platzierung von 3D-Objekten (Gltf und Obj/Mtl), Umgebunstextur.

Die Struktur des Programms:









siehe auch  [...] 

Die Bewegung eines Betrachters im Schauraun erfolgt mit einem speziell erstelltem Control oder der Tastatur ( Kursortasten, Ziffernblock ). Der Blick kann nach oben und unten gerichtet werden. Man definiert die begehbaren Bereiche in Form von angrenzenden bzw. sich überschneidenden Rechtecken, Kreisen und Dreiecken.
Siehe  [...] 

Die absolute Größe des Controls kann man mit der Anzeigegröße des Browsers ändern. Die 3D Szene wird davon nicht berührt. Der Mittelkreis des Controls dient zum verschieben des Controls. Ein Doppelklick darauf zeigt in der neuen Version die Geschwindigkei vorwärts an. Diese kann mit dem Schieber verändert werden. Ein weiterer Doppelklick auf die Mitte des Controls verbirgt die Geschwindigkeit wieder.

Das Gltf 3D-Modell des Betrachters kann sich selbst auf die Füße schauen und sich komplett im Spiegel sehen.

Gesonderte Ordner gibt es für Materialien, 3D-Objekte, Rahmen, Umgebunstextur.

Die Beispielbilder zeigen oft die Kontroll-Textur. Hier kann man die Varianten der Bestimmung der uv-Werte zur Nutzung von Ausschnitten aus einer Textur erkennen. Die wenigen anderen Texturen wurden entweder heruntergeladen (frei), selbst fotografiert oder mit dem Grafikprogramm Krita  [...]  (deutsche Oberfläche verfügbar) erstellt. Da ich kein Malkünstler bin, sind sie recht einfach.

BEISPIELBILDER

Startposition und Winkel, die Betrachterin sieht sich im Spiegel.

















von außerhalb gesehen



 
21.10.2020  
 




p.specht

Bitte mach alle Regenbogen-färbigen Flächen und bemaßten Bilder aus den Demos weg. Das ist das Einzige, was Normalos noch stört. Ansonsten: WOW!!! Ich Dödel kapiere zum ersten Mal, wohin die Reise geht: In ein professionelles Produkt! Jetzt noch ein Möbellager, aus dem man sich nach Betrachten ein Teil rauskopieren und "daheim" reinstellen oder aufhängen kann (am besten mit online-"hineinschieben" und Anrücken an die Wände), und selbst ich DAU kann das dann ohne Mathe-Studium verwenden. Die Devise wäre: Super einfach - einfach super! 
 
Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen, zB 'daß' statt 'das'...
21.10.2020  
 




HofK
p.specht (21.10.2020)
Bitte mach alle Regenbogen-färbigen Flächen und bemaßten Bilder aus den Demos weg. Das ist das Einzige, was Normalos noch stört.


Auf Discourse kamen zwei ähnliche Ratschläge.  [...] 

(übersetzt)
"Mir gefällt diese Idee, aber die abschließende Präsentation scheint sie irgendwie zu sabotieren. "
Mein Kommentar:
Zunächst bin ich nur an der Präsentation des Konzepts interessiert. Wenn Sie sich meine Addons  [...]  ansehen, werden Sie sehen, dass ich mich für mathematische Strukturen und interessante Algorithmen begeistere. Wie ich geschrieben habe, bin ich weder ein Künstler, noch ein guter Fotograf.

(übersetzt) "Wäre es nicht besser, zum Beispiel eine virtuelle Nachbildung eines Autohauses oder einen Kunstausstellungsraum zu präsentieren?  "
Mein Kommentar:
Genau für diesen Zweck ist es vorgesehen, dass jemand ohne Kenntnisse von JavaScript (abgesehen von der Einhaltung einiger Regeln für Klammern, Komma und Semikolon in den Designdateien) sein eigenes Objekt in einfacher Form erstellen und präsentieren kann.

Da die weitere Bearbeitung und Verwendung zur Zeit noch offen ist, werden Sie es auf Github nicht finden.
 
21.10.2020  
 




HofK
Ein Schauraum wird nie fertig werden, da man eine kaum überschaubare Fülle von Dingen hinzufügen kann. 

Deshalb jetzt eine Auszeit davon.


Ein anderes Projekt wartet bereits darauf in Angriff genommen zu werden.


Vor einigen Jahren habe ich die Simulation einer absolut minimalen 8 Bit CPU mit XProfanFree 11 realisiert.

Siehe  [...] 

Diese Seite hat einige Darstellungsfehler, die nicht einfach korrigiert werden können. Sie wurde mit einem Bausatz bei 1&1 erstellt. Nach der fehlerhaften Kündigung war dieser seitens 1&1 nicht wieder herstellbar. Ich kann nur im HTML- Quellcode einfache Änderungen/Zusätze machen.
Weitere Quellen zur Simulation [...]  [...] 

Ich will versuchen, die Simulation in eine Sprache, die weltweit bekannter ist, zu übertragen. Statt der 2D Darstellung im Windows-Fenster aber in 3D im Browser. Natürlich mit Hilfe von three.js.

Dazu habe ich die Beispiele meiner Sammlung aus Discourse  [...]  durchgesehen und eine Liste mit Kandidaten erstellt, die nützlich sein könnten.
________________________________________________________________

Instanced Mesh [...]  [...]  [...]  [...]  [...]  [...] 

grid box / cell [...]  [...]  [...]  [...] 

char [...] 

Fill Level dynamic [...] 

label and marker set/ remove - like a Checkbox inside ?? [...] 

change textur by time [...] 

HTML mixed in WebGL / DOM Label [...]  [...]  [...] 

text label annotation [...]  [...]  [...]  [...] 

_____

see extended examples
=> [...] 
- TransparentCylinderWithText
- AnnotationsMoveWithModel
- DOM-ContentOnObject
- AnimationHotspot
- ClockSevenSegment
- LineGrids-LineLabyrinths

_______________________________________________________________

Als Textdatei Herunterladen

Auch die offiziellen Beispielen von three.js  [...]  sind eine Fundgrube, aber oft recht komplex.

_______________________________________________________________

Zwei erste Tests beziehen sich auf die Darstellung der binären Werte im RAM und den Registern. Siehe  [...]  im oberen Bereich.



Mit instanced mesh, dort probieren  [...]  (Maus dreht Box)



Mit elementarer Geometrie, dort probieren  [...] 

Man kann die Techniken auch mischen. Optisch gefällt mir die Version mit dem Zylinder und dem Torus besser.
 
26.10.2020  
 




HofK
Der erste RAM Prototyp ist fertiggestellt.

Die Optik kann sich noch ändern, aber das programmtechnische Prinzip erscheint recht geeignet.

Die Konstruktion besteht aus drei instanced Meshes - durchsichtige Zelle, Symbol 0, Symbol 1.

Die Zelle wird immer angezeigt. Die Änderung des Symbols in der Zelle von 0 auf 1 und umgekehrt, wird durch Sichtbarkeit realisiert. Für die perspektivische Kamera in three.js gibt man den Bereich an, der abgebildet werden soll.

near — Camera frustum near plane.
far — Camera frustum far plane.


Mit der Definition einer Konstanten
invisible = -800
und der Angabe von
far als -invisible / 2
ist man auf der sicheren Seite, wenn man den Tiefenwert z auf invisible setzt. Die entspechende Instanz des instancded Mesh wird nicht dargestellt.
(Die negative z Achse zeigt in Richtung des Kamerablicks.)
 

Die Änderung der z Koordinate lässt sich einfach bewerkstelligen.

Zum Test ein 256 Byte RAM mit sich zufällig ändernden Werten. Initial sind alle Bits 0.

Testen:  [...] 


<!DOCTYPE html>
<!--  -->
<head>
<title> BinaryMemory </title>
<meta charset="utf-8" />
<style>

body {

    overflow: hidden;
    margin: 0;

}

</style>
</head>
<body> </body>
<script src="../js/three.min.121.js"></script>
<script src="../js/OrbitControls.121.js"></script>
<script>
'use strict'
const visible = 0;
const invisible = -800;
const camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.01, -invisible / 2 );
camera.position.set( 0, 0, 30 );
const scene = new THREE.Scene();
const renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
renderer.setClearColor( 0xeeeed3, 1 );
const light = new THREE.DirectionalLight( );
light.intensity = 0.2;
light.position.set( 20 , 150 , 150 );
scene.add( light );
new THREE.OrbitControls( camera, renderer.domElement );
const RAM = new THREE.Object3D();
const countRAM = 2048;// = 256 * 8;  256 Byte RAM
const transform = new THREE.Object3D();
const geoBox = new THREE.BoxBufferGeometry( 0.5, 0.85, 0.3 );
const matBox = new THREE.MeshBasicMaterial({color: 0xaaaaaa,  transparent: true,  opacity: 0.25 } );
const instMeshBox = new THREE.InstancedMesh( geoBox, matBox, countRAM );
positionInst( instMeshBox, visible );
RAM.add( instMeshBox );
const matDig = new THREE.MeshPhongMaterial( );
matDig.emissive.setRGB( 0, 0, 0 );
matDig.specular.setRGB( 0.4, 0.4, 0.4 );
const geoDig0 = new THREE.TorusBufferGeometry( 0.2, 0.05, 36, 36 );
const instMeshDig0 = new THREE.InstancedMesh( geoDig0, matDig, countRAM );
positionInst( instMeshDig0, visible );
RAM.add( instMeshDig0 );
const geoDig1 = new THREE.CylinderBufferGeometry( 0.05, 0.05, 0.48, 24 );
const instMeshDig1 = new THREE.InstancedMesh( geoDig1, matDig, countRAM );
positionInst( instMeshDig1, invisible );
RAM.add( instMeshDig1 )
scene.add( RAM );
RAM.position.y = 15;
let byteNo;
let bitNo;
animate();
// ........................................................................

function animate() {

    requestAnimationFrame( animate );
    byteNo = Math.floor( Math.random( ) * Math.floor( 256 ) );
    bitNo  = Math.floor( Math.random( ) * Math.floor(   8 ) );

    if ( Math.random( ) < 0.5 ) {

        visibilityRAM( instMeshDig0, byteNo, bitNo, invisible );
        visibilityRAM( instMeshDig1, byteNo, bitNo, visible );

    } else {

        visibilityRAM( instMeshDig0, byteNo, bitNo, visible );
        visibilityRAM( instMeshDig1, byteNo, bitNo, invisible );

    }

    instMeshDig0.instanceMatrix.needsUpdate = true;
    instMeshDig1.instanceMatrix.needsUpdate = true;
    renderer.render( scene, camera );

}

function positionInst( instMesh, z ) {

    let inst = 0;

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

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

            transform.position.set( 0.6 * j, -i, z );
            transform.updateMatrix();
            instMesh.setMatrixAt( inst, transform.matrix );
            inst ++;

        }

    }

}

function  visibilityRAM( instMesh, i, j, visibility ) {

    transform.position.set( 0.6 * j, -i, visibility );
    transform.updateMatrix( );
    instMesh.setMatrixAt( i * 8 + j, transform.matrix );

}

</script>
</html>
 
28.10.2020  
 




Antworten


Thementitel, max. 100 Zeichen.
 

Systemprofile:

Kein Systemprofil angelegt. [anlegen]

XProfan:

 Beitrag  Schrift  Smilies  ▼ 

Bitte anmelden um einen Beitrag zu verfassen.
 

Themenoptionen

332.642 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