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



HofK
In ein Labyrinth gehören auch einige Objekte.
Wie platziert man sie zufällig beim Start?
Das war die Frage. 

Die Lösung:



var insideLabyrinth = [];

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

for ( let j = 0; j < design2D[ i ].length; j ++) {

if ( design2D[ i ][ j ] === '+' ) insideLabyrinth.push( j , i ); // x, z positions

}

}

var tetra = new THREE.TetrahedronBufferGeometry( 0.45 );
var tetraMesh = new THREE.Mesh( tetra, materialUV );

var random = new Date().getMilliseconds() / 1000 ;

console.log( random +'s' ); ///////////////////

var idx = Math.floor( random * insideLabyrinth.length / 2 );

console.log( idx + ' idx ' ); ///////////////////

var posX = insideLabyrinth[ idx * 2 ];
var posZ = insideLabyrinth[ idx * 2 + 1 ];;

console.log( posX, posZ ); /////////////

tetraMesh.position.set( posX + 0.5, 0.3, posZ + 0.5);
mesh2D.add( tetraMesh );

Zwischenzeitlich habe ich die Labyrinth Geometrie in mein Addon THREEg.js eingebracht.  [...]  Dort befindet sich nun die finale Version. Beim Materialindex für 2D wird nun nur eine Eckige Klammer benötigt. Des 2D Design nutzt zur besseren Übersichtlichkeit und da dieses Zeichen bei 3D nicht auftritt nun + als Markierung.  [...] 
 
28.11.2018  
 




HofK
Nach Lösung des Labyrinth-Problems gab es eine weitere Frage  [...] 



und dann nach Lösung dieses Problems bei mir eine gedankliche Verknüpfung.

Daraus ist eine neue spezielle Geometrie entstanden. [...] 



Ich habe die Konstruktion von einfach zu gestaltenden Liniengittern realisiert. Damit kann man ganz einfach 2D-Linienlabyrinthe erstellen.

Die in den 3D-2D Labyrinthen verwendeten Designelemente können in einem Design kombiniert werden. Das Raster kann entweder in der xy-Ebene erstellt werden, oder an den Seiten eines Quaders.

Die Größe des Quaders wird standardmäßig durch das Design bestimmt, kann aber auch nach Bedarf angegeben werden. Die Länge der ersten Zeile des Designs jeder Seite ist entscheidend für die Zentrierung des Gitters. Man kann die Zentrierung leicht ändern, indem man Leerzeichen am Anfang und Ende verwendet.

Führt das Design zu Doppellinien an einer Stelle, wird die überschüssige Linie eliminiert. Ein wenig binäre Arithmetik genügt.
// delete double lines, uses 0bLeftFrontRightBack

for( let r = 1; r < rows; r ++ ) {

    cols = g.binDsgn[ s ][ r ].length;

    for( let c = 0; c < cols; c ++ ) {

        g.binDsgn[ s ][ r ][ c ] = ( ( g.binDsgn[ s ][ r - 1 ][ c ] & 0b0001 ) << 2 ) ^ g.binDsgn[ s ][ r ][ c ];

    }

}

for( let r = 0; r < rows; r ++ ) {

    cols = g.binDsgn[ s ][ r ].length;

    for( let c = 1; c < cols; c ++ ) {

        g.binDsgn[ s ][ r ][ c ] = ( ( g.binDsgn[ s ][ r ][ c - 1 ] & 0b0010 ) << 2 ) ^ g.binDsgn[ s ][ r ][ c ];

    }

}

for( let r = 0; r < rows; r ++ ) {

    cols = g.binDsgn[ s ][ r ].length;

    for( let c = 0; c < cols; c ++ ) {

        bin = g.binDsgn[ s ][ r ][ c ];
        g.lineCount += ( ( bin & 0b1000 ) >> 3 ) + ( ( bin & 0b0100 ) >> 2 ) + ( ( bin & 0b0010 ) >> 1 ) + ( bin & 0b0001 );

    }

}


Multimaterial wird im Seiten- und Ausrichtungsmodus unterstützt.

Dort ist das Beispiel zu obigem Bild: [...] 

Demnächst im Addon THREEg auch auf Github.
 
14.12.2018  
 




HofK
In three.js sind ganz bewusst nur einige grundlegende Geometrien definiert.

Eine Frage mit ausufernder Diskussion beschäftigt sich mit weiteren Körpern. [...] 

Mit einem Link [...]  konnte ich dann etwas Sinnvolles dazu beitragen. Dort
view-source:https://www.mathsisfun.com/geometry/images/poly-models.js
Interessant Zeile 644 ff 

In weiterer Folge der Diskussion habe ich ein sehr einfaches Beispiel einer BufferGeometry mit Normalen erstellt und auf threejs.hofk.de hinzugefügt. [...] 

 
23.12.2018  
 




p.specht

Gold-metallic: Besonders schwer darzustellen! Toll !
 
XProfan 11
Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen, zB 'daß' statt 'das'...
23.12.2018  
 




HofK
Immer noch zu der seeehr ausgedehnten Sache!

Nun wollten auch die Kanten nicht gleich parieren.

Also habe ich für den einfachen Fall des beliebigen Polygons ein kleines Beispiel erstellt.



schwingendes Fünfeck / swinging pentagon

Die Verfahrensweise lässt sich auf Polyeder erweitern.  
Dort schauen wie es schwingt:  [...] 
<!DOCTYPE html>
<!-- https://discourse.threejs.org/t/swinging-polygon/5509 -->
<!-- http://threejs.hofk.de/SwingingPolygon/SwingingPolygon.html -->
<head>
<title> SwingingPolygon </title>
<meta charset="utf-8" />
<style>

body {

    margin: 0;

}

</style>
</head>
<body>
</body>
<script src="../js/three.min.99.js"></script>
<script src="../js/OrbitControls.js"></script>
<script src="../js/THREEx.WindowResize.js"></script>
<script>
// @author hofk
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.01, 1000 );
camera.position.set( 0, 0, 20 );
var renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x44ff44, 1 );
var container = document.createElement('div' );
document.body.appendChild( container );
container.appendChild( renderer.domElement );
THREEx.WindowResize( renderer, camera );
var controls = new THREE.OrbitControls( camera, renderer.domElement );
scene.add( new THREE.AmbientLight( 0xffffff, 0.5) );
var light1 = new THREE.DirectionalLight( 0xeeffee, 0.8 );
light1.position.set( 0, 5, 9 );
scene.add( light1 );
//var material = new THREE.MeshPhongMaterial( { color: 0xff00ff, side: THREE.DoubleSide } );
var material = new THREE.MeshBasicMaterial( { color: 0xff00ff, side: THREE.DoubleSide, wireframe: true } );
//var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.VertexColors, side: THREE.DoubleSide } );
// .............. input values ....................
var corners = 5;// number of polygon corners
var detail = 20;// number of divisions of the edges
var c = {};// center point
c.x = 2;
c.y = 4;
c.z= -6;
var n = {};// polygone normal
n.x = 4;// .x and .y not both 0, simply for convenience, see e1
n.y = 2;
n.z = 1;
var r = 9;// radius
// ..................................................
// orthogonal unit vectors e1, e2 of polygon plane ( simplified calculation )
var e1 = {};
e1.x = -n.y;
e1.y =  n.x;
e1.z = 0;// see vector n
var e2 = {};
e2 = normalize( cross( e1, n ) );// see also https://threejs.org/docs/index.html#api/en/math/Vector3
e1 = normalize( e1 );
var geometry = new THREE.BufferGeometry( );
var cd = corners * detail;
var indices = new Uint32Array( cd * 3 );
var positions = new Float32Array( ( cd + 2 ) * 3 );// + last ( = first) and center point
//var normals = new Float32Array( cd * 3 );
var cors = [];// corners
var edgs = [];// edges
var v = {};

for( let i = 0, phi = 0; i < corners; i ++, phi += Math.PI * 2 / corners ) {

    // equation of circle in 3D space

    cors.push( {

        x: c.x + r * Math.cos( phi) * e1.x + r * Math.sin( phi ) * e2.x,
        y: c.y + r * Math.cos( phi) * e1.y + r * Math.sin( phi ) * e2.y,
        z: c.z + r * Math.cos( phi) * e1.z + r * Math.sin( phi ) * e2.z

    } );

}

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

    let j = i < corners - 1 ?  i + 1 : 0;

    edgs.push( {

        x: cors[ j ].x  - cors[ i ].x,
        y: cors[ j ].y  - cors[ i ].y,
        z: cors[ j ].z  - cors[ i ].z

    } );

}

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

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

        v = {

            x: cors[ i ].x + j / detail * edgs[ i ].x,
            y: cors[ i ].y + j / detail * edgs[ i ].y,
            z: cors[ i ].z + j / detail * edgs[ i ].z

        }

        positions[ ( i * detail + j ) * 3 ] = v.x;
        positions[ ( i * detail + j ) * 3  + 1 ] = v.y;
        positions[ ( i * detail + j ) * 3  + 2 ] = v.z;

    }

}

// last point equals first point
positions[ cd * 3 ] = positions[ 0 ];
positions[ cd * 3 + 1 ] = positions[ 1 ];
positions[ cd * 3 + 2 ] = positions[ 2 ];
// center point
positions[ cd * 3 + 3 ] = c.x;
positions[ cd * 3 + 4 ] = c.y;
positions[ cd * 3 + 5 ] = c.z;

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

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

        idx1 = i * detail + j;
        idx2 = i * detail + j + 1;
        indices[ ( i * detail + j ) * 3 ] = cd + 1;
        indices[ ( i * detail + j ) * 3 + 1 ] = idx1;
        indices[ ( i * detail + j ) * 3 + 2 ] = idx2;

    }

}

var pos = [];

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

    pos[ i ] = positions[ i ];

}

geometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );
geometry.addAttribute('position', new THREE.BufferAttribute( positions, 3 ).setDynamic( true ) );
//geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ));
geometry.computeVertexNormals( );// from three.js core
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
var t = 0;
animate();

function animate() {

    requestAnimationFrame( animate );
    t += 0.01;

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

        swinging( i , t );

    }

    geometry.attributes.position.needsUpdate = true;
    renderer.render( scene, camera );
    controls.update();

}

function swinging( i , t ) {

    let swingX, swingY, swingZ ;

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

        // ....... swinging function .......
        swingX = n.x * 0.1 * Math.sin( j / detail * Math.PI * 4 + t );
        swingY = n.y * 0.05 * Math.cos( j / detail * Math.PI * 4 + t );
        swingZ = n.z * 0.03 * Math.sin( j / detail * Math.PI * 4 + t );
        // .................................
        positions[ ( i * detail + j ) * 3 ]      = pos[ ( i * detail + j ) * 3 ] + swingX;
        positions[ ( i * detail + j ) * 3  + 1 ] = pos[ ( i * detail + j ) * 3  + 1 ] + swingY;
        positions[ ( i * detail + j ) * 3  + 2 ] = pos[ ( i * detail + j ) * 3  + 2 ] + swingZ;
        // last point equals first point
        positions[ cd * 3 ] = positions[ 0 ];
        positions[ cd * 3 + 1 ] = positions[ 1 ];
        positions[ cd * 3 + 2 ] = positions[ 2 ];

    }

}

function cross( v1, v2 ) {

    let v = {};
    v.x = v1.y * v2.z - v1.z * v2.y;
    v.y = v1.z * v2.x - v1.x * v2.z;
    v.z = v1.x * v2.y - v1.y * v2.x;
    return v;

}

function normalize( v ) {

    let l = Math.sqrt( v.x * v.x + v.y * v.y + v.z * v.z );
    let vn = {};
    vn.x = v.x / l;
    vn.y = v.y / l;
    vn.z = v.z / l;
    return vn;

}

</script>
</html>
 
27.12.2018  
 




HofK
Pünktlich zu Sylvester.

Da kann man Neujahr am Computer nicht verpassen. [...]  [...] 



von prisoner849 

 
31.12.2018  
 




HofK
Auf discourse.threejs.org  [...]  haben sich mittlerweile recht viele brauchbare Beispiele angesammelt. Damit die Sache nicht unüberschaubar wir, habe ich die Gliederung in Jahre vorgenommen. Da zwei Jahre abgeschlossen sind, stehen diese auch zum Download bereit.

So kann man auch lokal sehr einfach damit arbeiten. Die Texturen und Modelle hat man bei einigen Basisbeispielen dann auf dem Rechner. Mit Firefox kann man sie auch problemlos lokal laden. Natürlich kann man sich auch die Mühe machen und einen lokalen Server aufsetzen.



unter discourse.threejs.hofk.de/

Der direkte (alte) Link für die erweiterten Beispiele  [...]  wird umgeleitet.
 
09.01.2019  
 




HofK
Der Schauraum benötigt einige Rahmen für Fenster, Türen und Bilder.

Dazu habe ich die Lösung von prisoner849 benutzt.  [...] 

Allerdings ist bei dieser Lösung kein Multimaterial machbar.
Deshalb möchte ich die Rahmen in einer detaillierten Konstruktion grafisch erstellen und so auch Multimaterial ermöglichen.

Als erster Schritt ist die Konstruktionsbasis fertiggestellt.  [...]  [...] 

Sie gründet sich auf die Lösung von looeee  [...]  und erweitert diese um die Möglichkeit der vertikalen Verschiebung.



So kann die linke obere Szene in der Größe verändert werden. Dort kann man in zwei separaten Koordinatensystemen Marker setzen. Trifft man auf einen Marker, ändert sich die Farbe des Fadenkreuzes. In Firefox folgt das Kreuz dem Kursor recht flott, Chrom trödelt.

In der rechten Szene wird später die fertige 3D Konstruktion dargestellt. Bisher nur ein Testkörper.

Anschließend wird dann die three.js Definition der BufferGeometry exportiert. Wie das geht, kann man in meinem Beispiel  [...]  sehen.
<!DOCTYPE html>
<!-- @author hofk -->
<!-- based on @author: looeee  SceneComparsion   https://codepen.io/looeee/pen/jpebjN -->
<head>
<title> ConstructionBasis </title>
<meta charset="utf-8" />
<style>
/* style based on @author: looeee */

body {

    margin: 0px;
    overflow: hidden;
    text-align: center;
    background-color: #66ccff;

}

.container {

    position: absolute;
    top: 0;
    z-index: -1;
    width: 100%;
    height: 100%;

}

* {box-sizing: border-box;}

.comp {

    position: absolute;
    width: 100%;
    height: 100%;
    overflow: hidden;

}

.comp canvas {

    display: block;
    vertical-align: middle;

}

.slider {

    position: absolute;
    z-index: 9;
    cursor:nw-resize;
    width: 40px;
    height: 40px;
    background-color: #2196F3;
    opacity: 0.7;
    border-radius: 50%;

}

</style>
</head>
<body>
<div class="container">
<div class="comp containerA"></div>
<div class="slider"> </div>
<div class="comp containerB"></div>
</div>
</body>
<script src="../js/three.min.100.js"></script>
<script src="../js/OrbitControls.js"></script>
<script>
// @author hofk
'use strict'
var containerA;
var containerB;
var slider;
var cameraA;
var cameraB;
var rendererA;
var rendererB;
var sceneA;
var sceneB;
var controlsA;
var controlsB;
var matMarkerL;
var matMarkerR;
var markerSize;
var aspectB;
var gBPointsL;
var gBPointsR;
var gReticle;
var matReticle;
var reticle;
var matReticleM;
var reticleM;
var markersL = [];
var markersR = [];
var idxMarkersL = -1;
var idxMarkersR = -1;
var epsilon = 0.004;
var idxHitL = -1;
var idxHitR = -1;
var posCount = 600;
containerA = document.querySelector('.containerA' );
containerB = document.querySelector('.containerB' );
slider = document.querySelector('.slider' );
containerB.addEventListener('mousemove', onContainerBMouseMove );
containerB.addEventListener('mouseup', onContainerBmouseUp );
// create  scenes
sceneA = new THREE.Scene();
sceneA.background = new THREE.Color( 0x555555 );
sceneB = new THREE.Scene();
sceneB.background = new THREE.Color( 0xeeeeee );
// perspective / orthographic camera
cameraA = new THREE.PerspectiveCamera( 55, containerA.clientWidth / containerA.clientHeight, 0.1, 200 );
cameraA.position.set( 0, 0, 6 );
var widthB = containerB.clientWidth;
var heightB = containerB.clientHeight;

if ( widthB > 2 * heightB ) {

    widthB = 2 * heightB;

} else {

    heightB = widthB / 2;

}

aspectB = widthB / heightB;
cameraB = new THREE.OrthographicCamera( -aspectB, aspectB, 1, -1, 0.01, 10 );
cameraB.position.set( 0, 0, 0.1 );
// controls
controlsA = new THREE.OrbitControls( cameraA, containerA );// only controlsA
// lights
const lightA = new THREE.DirectionalLight();
lightA.position.set( 20, 20, 20 );
sceneA.add( lightA );
// renderer
rendererA = new THREE.WebGLRenderer( { antialias: true } );
rendererA.setSize( containerA.clientWidth, containerA.clientHeight );
rendererA.setPixelRatio( window.devicePixelRatio )
containerA.appendChild( rendererA.domElement );
rendererB = new THREE.WebGLRenderer( { antialias: true } );
rendererB.setSize( widthB, heightB );
rendererB.setPixelRatio( window.devicePixelRatio );
containerB.appendChild( rendererB.domElement );
// .....................only TEST: geometry/mesh A ...........................................
const geoA = new THREE.CylinderBufferGeometry( 1, 1, 2, 10, 10  );
const matA = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
const meshA = new THREE.Mesh( geoA, matA );
meshA.position.x = 3;
sceneA.add( meshA );
//................................................................
createDesignArea( );
defineReticles( );

rendererA.setAnimationLoop( () => {

    update();
    render();

} );

rendererB.setAnimationLoop( () => {

    update();
    render();

} );

initComparisons();
// -------------------------------------------

function createDesignArea( ){

    var gB1 = new THREE.BufferGeometry( );
    var pos = [];

    for ( let i = 1; i < 10; i ++ ) {

        let j = i / 10;
        rasterPosPush( j );

    }

    gB1.lineCount = 54;
    gB1.positions = new Float32Array( gB1.lineCount * 6 );
    for ( let i = 0; i < pos.length; i ++ )	gB1.positions[ i ] = pos[ i ];
    gB1.addAttribute('position', new THREE.BufferAttribute( gB1.positions, 3 ) );
    var matB1 = new THREE.LineBasicMaterial( { color: 0xcccccc } );
    var gridB1 = new THREE.LineSegments( gB1, matB1 );
    sceneB.add( gridB1 );
    //.....
    var gB0 = new THREE.BufferGeometry( );
    pos = [];
    pos.push( -2,0,0, -0.02,0,0 );// horizontal
    pos.push( 0.02,0,0, 2,0,0 );
    pos.push( -1,-1,0, -1,1,0 );// vertical
    pos.push( 1,-1,0, 1,1,0 );
    gB0.lineCount = 4;
    gB0.positions = new Float32Array( gB0.lineCount * 6 );
    for ( let i = 0; i < pos.length; i ++ )	gB0.positions[ i ] = pos[ i ];
    gB0.addAttribute('position', new THREE.BufferAttribute( gB0.positions, 3 ) );
    var matB0 = new THREE.LineBasicMaterial( { color: 0x888888 } );
    var gridB0 = new THREE.LineSegments( gB0, matB0 );
    sceneB.add( gridB0 );
    //.....
    var gBsplit = new THREE.BufferGeometry( );
    gBsplit.positions = new Float32Array( 6 );
    gBsplit.positions[ 0 ] = gBsplit.positions[ 2 ] = gBsplit.positions[ 3 ] = gBsplit.positions[ 5 ] = 0;
    gBsplit.positions[ 1 ] = -1;
    gBsplit.positions[ 4 ] = 1;
    gBsplit.addAttribute('position', new THREE.BufferAttribute( gBsplit.positions, 3 ) );
    var matBsplit = new THREE.LineBasicMaterial( { color: 0xffffff } );
    var gridBsplit = new THREE.LineSegments( gBsplit, matBsplit );
    sceneB.add( gridBsplit );
    //.....
    markerSize = 0.015;
    matMarkerL = new THREE.MeshBasicMaterial( { color: 0x00aaaa, transparent: true, opacity: 0.5 } );
    matMarkerR = new THREE.MeshBasicMaterial( { color: 0xaa00aa, transparent: true, opacity: 0.5 } );
    //.....
    gBPointsL = new THREE.BufferGeometry( );
    gBPointsL.positions = new Float32Array( posCount );
    gBPointsR = new THREE.BufferGeometry( );
    gBPointsR.positions = new Float32Array( posCount );
    // detail function

    function rasterPosPush( j ){

        pos.push( -2, j, 0,  2, j, 0 );// horizontal
        pos.push( -2, -j, 0,  2, -j, 0 );
        pos.push( -2+j, -1, 0,  -2+j, 1, 0 );// vertical
        pos.push( -1+j, -1, 0,  -1+j, 1, 0 );
        pos.push(  1-j, -1, 0,   1-j, 1, 0 );
        pos.push(  2-j, -1, 0,   2-j, 1, 0 );

    }

}

function defineReticles( ) {

    gReticle = new THREE.BufferGeometry( );
    gReticle.positions = new Float32Array( 4 * 3 );
    gReticle.positions[  0 ] = 0;
    gReticle.positions[  1 ] = -0.02;
    gReticle.positions[  2 ] = 0;
    gReticle.positions[  3 ] = 0;
    gReticle.positions[  4 ] = 0.02;
    gReticle.positions[  5 ] = 0;
    gReticle.positions[  6 ] = -0.02;
    gReticle.positions[  7 ] = 0;
    gReticle.positions[  8 ] = 0;
    gReticle.positions[  9 ] = 0.02;
    gReticle.positions[ 10 ] = 0;
    gReticle.positions[ 11 ] = 0;
    gReticle.addAttribute('position', new THREE.BufferAttribute( gReticle.positions, 3 ) );
    matReticle = new THREE.LineBasicMaterial( { color: 0xff0000 } );// hit
    reticle = new THREE.LineSegments( gReticle, matReticle );
    sceneB.add( reticle );
    reticle.visible = false;
    matReticleM = new THREE.LineBasicMaterial( { color: 0x444444 } );// Move
    reticleM = new THREE.LineSegments( gReticle, matReticleM );
    sceneB.add( reticleM );
    reticleM.visible = true;

}

function onContainerBMouseMove( event ) {

    event.preventDefault();
    var markerX = Math.round( 100 * ( event.clientX / widthB * 4 - 2 ) ) / 100;
    var markerY = Math.round( 100 * ( -event.clientY / heightB * 2 + 1 ) ) / 100;
    reticle.position.set( markerX, markerY, 0 );

    if( markerX === 0 ) {

        reticleM.visible = false;

    }

    if( markerX < 0 ) {// left

        if ( hitMarkerL( markerX, markerY ) === -1 ) {

            reticleM.visible = true;
            reticleM.position.set( markerX, markerY, 0 );
            reticle.visible = false;

        } else {

            reticleM.visible = false;
            reticle.visible = true;
            reticle.position.set( markerX, markerY, 0 );

        }

    }

    if( markerX > 0 ) {// right

        if ( hitMarkerR( markerX, markerY ) === -1 ) {

            reticleM.visible = true;
            reticleM.position.set( markerX, markerY, 0 );
            reticle.visible = false;

        } else {

            reticleM.visible = false;
            reticle.visible = true;
            reticle.position.set( markerX, markerY, 0 );

        }

    }

}

function onContainerBmouseUp( event ) {

    event.preventDefault();
    var markerX = Math.round( 100 * ( event.clientX / widthB * 4 - 2 ) ) / 100;
    var markerY = Math.round( 100 * ( -event.clientY / heightB * 2 + 1 ) ) / 100;

    if ( markerX < 0 ) {// left

        idxMarkersL ++;
        markersL[ idxMarkersL ] = new THREE.Sprite( matMarkerL );
        markersL[ idxMarkersL ].position.x = markerX;
        markersL[ idxMarkersL ].position.y = markerY;
        markersL[ idxMarkersL ].scale.x = markerSize;
        markersL[ idxMarkersL ].scale.y = markerSize;
        sceneB.add( markersL[ idxMarkersL ] );

        for ( let i = idxMarkersL * 3 ; i < gBPointsL.positions.length; i += 3 ) {// fill with last value

            gBPointsL.positions[ i ] = markerX;
            gBPointsL.positions[ i + 1 ] = markerY;
            gBPointsL.positions[ i + 2 ] = 0;

        }

    }

    if ( markerX > 0 ) {// right

        idxMarkersR ++;
        markersR[ idxMarkersR ] = new THREE.Sprite( matMarkerR );
        markersR[ idxMarkersR ].position.x = markerX;
        markersR[ idxMarkersR ].position.y = markerY;
        markersR[ idxMarkersR ].scale.x = markerSize;
        markersR[ idxMarkersR ].scale.y = markerSize;
        sceneB.add( markersR[ idxMarkersR ] );

        for ( let i = idxMarkersR * 3 ; i < gBPointsR.positions.length; i += 3 ) {// fill with last value

            gBPointsR.positions[ i ] = markerX;
            gBPointsR.positions[ i + 1 ] = markerY;
            gBPointsR.positions[ i + 2 ] = 0;

        }

    }

}

function hitMarkerL( markerX, markerY ) {

    var x0;
    var x1;
    var y0;
    var y1;
    var hitL = false;
    var j = idxMarkersL * 3 + 3;

    while ( !hitL &&  j > 2  ) {

        j -= 3;
        x0 = gBPointsL.positions[ j ] - epsilon;
        x1 = gBPointsL.positions[ j ] + epsilon;
        y0 = gBPointsL.positions[ j + 1 ] - epsilon;
        y1 = gBPointsL.positions[ j + 1 ] + epsilon;
        hitL = ( markerX > x0 ) && ( markerX < x1 ) && ( markerY > y0 ) && ( markerY < y1 );

    }

    return hitL ? j : -1;// idxHitL

}

function hitMarkerR( markerX, markerY ) {

    var x0;
    var x1;
    var y0;
    var y1;
    var hitR = false;
    var j = idxMarkersR * 3 + 3;

    while ( !hitR &&  j > 2  ) {

        j -= 3;
        x0 = gBPointsR.positions[ j ] - epsilon;
        x1 = gBPointsR.positions[ j ] + epsilon;
        y0 = gBPointsR.positions[ j + 1 ] - epsilon;
        y1 = gBPointsR.positions[ j + 1 ] + epsilon;
        hitR = ( markerX > x0 ) && ( markerX < x1 ) && ( markerY > y0 ) && ( markerY < y1 );

    }

    return hitR ? j : -1;// idxHitR

}

function update() {

    // ??????

}

function render() {

    rendererA.render( sceneA, cameraA );
    rendererB.render( sceneB, cameraB );

}

function initComparisons() {

    // modified/ extended ( based on @author: looeee )
    containerB.style.width = ( 0.75 * containerB.offsetWidth ) +'px';
    containerB.style.height = ( 0.75 * containerB.offsetHeight ) +'px';
    let pX = containerB.offsetWidth;
    let pY = containerB.offsetHeight;

    if ( pX > widthB ) {

        slider.style.left = widthB - 20 + "px";

    } else {

        slider.style.left = pX - 20 + "px";

    }

    if ( pY > heightB ) {

        slider.style.top = heightB - 20 + "px";

    } else {

        slider.style.top = pY - 20 + "px";

    }

    let clicked = 0;
    // only controlsA

    const slideReady = () => {

        clicked = 1;
        controlsA.enabled = false;

    };

    const slideFinish = () => {

        clicked = 0;
        controlsA.enabled = true;

    };

    const slideMove = ( e ) => {

        if ( clicked === 0 ) return false;

            let posX = getCursorPosX( e );
            let posY = getCursorPosY( e );
            //prevent the slider from being positioned outside the canvas

            if ( posX < 0 ) posX = 0;

                if ( posX > widthB ) posX = widthB;

                    slideX( posX );

                    if ( posY < 0 ) posY = 0;

                        if ( posY > heightB ) posY = heightB;

                            slideY( posY );

                        }

                        //detail functions

                        function getCursorPosX( e ) {

                            let getCur = ( e.pageX - containerB.offsetLeft ) - window.pageXOffset;
                            return getCur;

                        }

                        function getCursorPosY( e ) {

                            let getCur = ( e.pageY - containerB.offsetTop ) - window.pageYOffset;
                            return getCur;

                        }

                        function slideX(x) {

                            containerB.style.width = x + "px";
                            //position the slider
                            slider.style.left = containerB.offsetWidth - ( 0.5 * slider.offsetWidth) + "px";

                        }

                        function slideY(y) {

                            containerB.style.height = y + "px";
                            //position the slider
                            slider.style.top = containerB.offsetHeight - ( 0.5 * slider.offsetHeight) + "px";

                        }

                        slider.addEventListener('mousedown', slideReady );
                        window.addEventListener('mouseup', slideFinish );
                        window.addEventListener('mousemove', slideMove );

                    }

                    </script>
                    </html>
 
12.01.2019  
 




HofK
Die Geometriedefinition für Rahmen mit Multimaterial ist fertig.
Dabei gibt es zwei verschiedene Modi.

In 7 Farben








Anders als in der Lösung von prisoner849  [...]  benutze ich neben THREE.BufferGeometry( ) keine weiteren Objekte von three.js.

Damit wird es einfach Multimaterial zu ermöglichen. Für Texturen benötigt man uv Werte. In der allgemeinen Form macht das wenig Sinn. Hat man allerdings eine konkrete Form wie einen Türrahmen, kann man die uv Werte leicht ermitteln und integrieren.

Hier der Link:  [...] 

Ich werde die Geometrie in mein Addon THREEg  [...]  aufnehmen.
<!DOCTYPE html>
<!-- https://discourse.threejs.org/t/profiledcontourgeometry-multimaterial/5801 -->
<!-- http://threejs.hofk.de/ProfiledContourGeometryMM/ProfiledContourGeometryMM.html -->
<head>
<title> ProfiledContourGeometryMM  </title>
<meta charset="utf-8" />
<style>

body {

    margin: 0;

}

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

for ( var i = 0; i < detail + 1; i ++ ){

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

}

var contour1 = [
-3,  4,
0,  4,
4,  4,
2,  1,
4, -2,
0, -3,
-4, -3,
-4,  0
];
var profileShape2 = [ -1,1, 1,1, 1,-1, -1,-1 ];
var contour2 = [
4, 0,
4, 8,
8, 8,
12, 8,
12, 2,// here only to show that angle of 180° vertikal works
12, 0,
];
var materials = [// rainbow-colored
new THREE.MeshPhongMaterial( { color: 0xfa0001, side: THREE.DoubleSide } ),
new THREE.MeshPhongMaterial( { color: 0xff7b00, side: THREE.DoubleSide } ),
new THREE.MeshPhongMaterial( { color: 0xf9f901, side: THREE.DoubleSide } ),
new THREE.MeshPhongMaterial( { color: 0x008601, side: THREE.DoubleSide } ),
new THREE.MeshPhongMaterial( { color: 0x01bbbb, side: THREE.DoubleSide } ),
new THREE.MeshPhongMaterial( { color: 0x250290, side: THREE.DoubleSide } ),
new THREE.MeshPhongMaterial( { color: 0xfc4ea5, side: THREE.DoubleSide } ),
new THREE.MeshPhongMaterial( { color: 0x83058a, side: THREE.DoubleSide } ),
new THREE.MeshPhongMaterial( { color: 0x83058a, side: THREE.DoubleSide } )
]
var material = materials[ 2 ].clone();
material.wireframe = true;
//..................................................... contourClosed, openEnded, profileMaterial
var geometry1 = ProfiledContourMMgeometry(profileShape1, contour1, false, false, true );
var fullProfile1 = new THREE.Mesh( geometry1, materials );
fullProfile1.position.z = 6;
scene.add( fullProfile1 );
var fullProfile12 = new THREE.Mesh( geometry1, material );
fullProfile12.position.z = -8;
scene.add( fullProfile12 );
var geometry13 = ProfiledContourMMgeometry(profileShape1, contour1 );
var fullProfile13 = new THREE.Mesh( geometry13, materials );
fullProfile13.position.x = -5;
scene.add( fullProfile13 );
var geometry2 = ProfiledContourMMgeometry(profileShape2, contour2, false, true );
var fullProfile2 = new THREE.Mesh( geometry2, materials );
fullProfile2.scale.set( 0.5, 0.5, 0.5 );
scene.add( fullProfile2 );
render();

function render() {

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

}

function ProfiledContourMMgeometry( profileShape, contour, contourClosed, openEnded, profileMaterial ) {

    contourClosed = contourClosed !== undefined ? contourClosed : true;
    openEnded = openEnded !== undefined ? openEnded : false;
    openEnded = contourClosed === true ? false : openEnded;
    profileMaterial = profileMaterial !== undefined ? profileMaterial : false;
    if( contourClosed ) contour.push( contour[ 0 ], contour[ 1 ] );
    var hs1 = contour.length / 2;
    var rs1 = profileShape.length / 2;
    var hs = hs1 - 1;// height segments
    var rs = rs1 - 1;// radius segments
    var faceCount = hs * rs * 2 + ( openEnded ? 0 : rs * 2 );
    var posCount = hs1 * rs1 + ( openEnded ? 0 : 2 );
    var g = new THREE.BufferGeometry( );
    g.indices = new Uint32Array( faceCount * 3 );
    g.positions = new Float32Array( posCount * 3 );
    g.setIndex( new THREE.BufferAttribute( g.indices, 1 ) );
    g.addAttribute('position', new THREE.BufferAttribute( g.positions, 3 ) );
    var a, b1, c1, b2, c2;
    var i1, i2;
    var xc0, yc0, xc1, yc1, xc2, yc2, xSh, xDiv;
    var dx0, dy0, dx2, dy2;
    var e0x, e0y,e0Length, e2x, e2y, e2Length, ex, ey, eLength;
    var phi, bend;
    var x, y, z;
    var vIdx, posIdx;
    var epsilon = 0.000001;
    var idx = 0;

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

        if ( profileMaterial ) g.addGroup( idx, rs * 6, i );// MultiMaterial support

            i1 = i + 1;

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

                // 2 faces / segment,  3 vertex indices
                a =  rs1 * i + j;
                c1 = rs1 * i1 + j;// left
                b1 = c1 + 1;
                //c2 = b1;         // right
                b2 = a + 1;
                g.indices[ idx     ] = a;// left
                g.indices[ idx + 1 ] = b1;
                g.indices[ idx + 2 ] = c1;
                g.indices[ idx + 3 ] = a;// right
                g.indices[ idx + 4 ] = b2,
                g.indices[ idx + 5 ] = b1;// = c2

                if ( !profileMaterial ) g.addGroup( idx, 6, j );// MultiMaterial support

                    idx += 6;

                }

            }

            if( !openEnded ) {

                g.addGroup( idx, rs * 3, rs );// MultiMaterial support
                a = hs1 * rs1;

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

                    g.indices[ idx     ] = a;
                    g.indices[ idx + 1 ] = j + 1;
                    g.indices[ idx + 2 ] = j;
                    idx += 3;

                }

                g.addGroup( idx, rs * 3, rs + 1 );// MultiMaterial support
                a += 1;

                for ( var j = rs1 + 1; j > 1; j -- ) {

                    g.indices[ idx     ] = a;
                    g.indices[ idx + 1 ] = a - j;
                    g.indices[ idx + 2 ] = a - j + 1;
                    idx += 3;

                }

            }

            for ( var 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 );

                }

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

                    xSh = profileShape[ j * 2 ];
                    x = xc1 + xSh / xDiv * bend * ex;
                    y = yc1 + xSh / xDiv * bend * ey;
                    z = profileShape[ j * 2 + 1 ];// ySh
                    vIdx = rs1 * i + j;
                    posIdx = vIdx * 3;
                    g.positions[ posIdx ] = x;
                    g.positions[ posIdx + 1 ] = y;
                    g.positions[ posIdx + 2 ] = z;

                }

            }

            if( !openEnded ) {

                g.positions[ hs1 * rs1 * 3 ] = contour[ 0 ];
                g.positions[ hs1 * rs1 * 3 + 1 ] = contour[ 1 ];
                g.positions[ hs1 * rs1 * 3 + 2 ] = 0;
                g.positions[ hs1 * rs1 * 3 + 3 ] = contour[ hs * 2 ];
                g.positions[ hs1 * rs1 * 3 + 4 ] = contour[ hs * 2 + 1 ];
                g.positions[ hs1 * rs1 * 3 + 5 ] = 0;

            }

            g.computeVertexNormals();
            return g;

        }

        </script>
        </html>
 
18.01.2019  
 




HofK
Die Rahmengeometrie ist in das Addon THREEg integriert und auf Github  [...]  verfügbar.

Auch die Konstruktion macht Fortschritte.
Man kann schon Punkte setzen, verschieben, löschen und einfügen.
Für beide Koordinatensysteme kann ein Maßstab unabhängig gewählt werden.

 
19.01.2019  
 




HofK
Da einige Autoren auch im neuen Jahr schon fleißig waren, gibt es interessante Beispiele von discourse.threejs.org in der Sammlung  [...] 

 
24.01.2019  
 




HofK
Beim einfügen der Rahmen habe ich festgestellt, dass es sehr ungünstig ist, wenn man für jede Wandöffnung extra Teilwände definieren muss. Also davor, bei Türen über, bei Fenstern dazu noch unter und dann hinter der Wandöffnung. Hinzu kommt das Problem der Textur. Möchte man eine einheitlich strukturierte Wand haben, ist der Aufwand zur Ermittlung und Eintragung der uv-Werte für die Teilwände nicht unerheblich. Dann wird die Sache auch schnell unübersichtlich.

Alter Zustand: Das Problem einfach mit Backstein über der Tür umgangen.



Also habe ich für "dünne" Wände - Aussenwände - eine einheitliche Definition ermöglicht.

// bei unterschiedlichem Niveau zu Anfangspunkt Höhen y00,y01 einfügen

// x0,z0, (y00,y01,) x1,z1, y10,y11 ( , Dicke ) oder ( ,Wandöffnungen ) ( optional )


Beispiel:

[ 0,2, 0,12, 0,4, 1,1,1,1.5, 1,2,0,2.5, 1,1,1,1.5 ], // 3 Wandöffnungen

Wandöffnungen d, w, l, h - distance, width, level, height

Da der Koordinatenursprung hinten rechts in der Ecke ist, sind die Werte (vom Innenraum aus gesehen ) von rechts nach links zu werten. Die Wand steht auf der z Achse.



Das Verfahren funktioniert auch mit Wänden die beliebig schräg im Raum stehen und auch mit unterschiedlichen Werten für die Höhen von Anfangs- und Endpunkt der Wand.

Bei der Anwendung ist nun der Aufwand geringer, im Javascript ein wenig größer.

Die Handhabung der optionalen Werte:


wls = [];

wallGeometries[ w ] = new THREE.BufferGeometry();

wls.push( walls[ w ][ 0 ], walls[ w ][ 1 ] ); // x0,z0,

thick = ( walls[ w ].length === 7 || walls[ w ].length === 9 ) ? true : false;
equlev = ( walls[ w ].length - 2 ) % 4 < 2 ? true: false;

if ( equlev ) {

wls.push( walls[ w ][ 4 ], walls[ w ][ 5 ] ); // (y00,y01,) <-- y10,y11 (identical, equal level)
wls.push( walls[ w ][ 2 ], walls[ w ][ 3 ], walls[ w ][ 4 ], walls[ w ][ 5 ] ); // x1,z1, y10,y11

} else {

wls.push( walls[ w ][ 2 ], walls[ w ][ 3 ], walls[ w ][ 4 ], walls[ w ][ 5 ], walls[ w ][ 6 ], walls[ w ][ 7 ] );

}

if ( equlev && thick ) wls.push( walls[ w ][ 6 ] );
if ( !equlev && thick ) wls.push( walls[ w ][ 8 ] );

if( !thick ) {

for ( let i = 6 + ( equlev ? 0 : 2 ); i < walls[ w ].length; i += 4 ) { // each 4 values wall openings

wls.push( walls[ w ][ i ], walls[ w ][ i + 1 ], walls[ w ][ i + 2 ], walls[ w ][ i + 3 ] );

}

}

Dazu kommen dann noch einige Berechnungen zur Bestimmung der Positionsanzahl und zur Bestimmung der Positionen und uv-Werte.
Man benötigt die Gleichung der Geraden im Raum. 
 
02.02.2019  
 




Antworten


Thementitel, max. 100 Zeichen.
 

Systemprofile:

Kein Systemprofil angelegt. [anlegen]

XProfan:

 Beitrag  Schrift  Smilies  ▼ 

Bitte anmelden um einen Beitrag zu verfassen.
 

Themenoptionen

332.759 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