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



HofK
Auf die Frage "How to remove interior faces while keeping exterior faces untouched?" in discourse.threejs.org  [...]  hatte prisoner849 wieder eine effiziente Lösung.

Es ging um ein Labyrinth.

Zu der Lösung habe ich eine vereinfachte Basislösung erstellt.  [...]  und  [...] 

Dann kam mir der Gedanke, dass man mit dieser Methode sehr leicht komplexere 3D Labyrinthe erstellen kann. Es brauchte nur noch einer geeigneten Designsymbolik.

Ein Ergebnis:



siehe  [...]  [...] 
<!DOCTYPE html>
<!-- https://discourse.threejs.org/t/how-to-remove-interior-faces-while-keeping-exterior-faces-untouched/4869/19 -->
<!-- http://threejs.hofk.de/BoxLabyrinthCreation3D/BoxLabyrinthCreation3D.html -->
<head>
<title> BoxLabyrinthCreation3D </title>
<meta charset="utf-8" />
</head>
<body>
</body>
<script src="../js/three.min.98.js"></script>
<script src="../js/BufferGeometryUtils.js"></script> <!-- not in the core -->
<script src="../js/OrbitControls.js"></script>
<script src="../js/THREEx.WindowResize.js"></script>
<script>
// @author hofk
'use strict';
/*_______________________________________________
icons
The characters on the keyboard have been chosen so that they roughly reflect the form.
wall description
sides l f r b is left front right back, with floor and roof
char sides
G	l f r b   can only be achieved by beaming
M	l f r
C	b l f
3	f r b
U	l b r
H	l r
:	f b
F	l f
7	f r
L	l b
J	b r
I	l
1	r
-	f
.	b
without walls
since extra character not possible on the wall
* roof and floor
^ roofless
v floorless
x roofless and floorless
with four side walls but roofless and floorless
#
_________________________________________________*/
var designBoxLabyrinth3D = [
// upper storey first
//23456789.......
[
'     M         G', // 1
'     H          ', // 2
'     H          ', // 3
'   F-*--7       ', // 4
'   I*7**1       ', // 5
' C:v*L.**:::7   ', // 6
'   L*...J   U   ', // 7
'    H           ', // 8
'    L::::3      '  // 9
],[
'                ', // 1
'                ', // 2
'                ', // 3
'                ', // 4
'                ', // 5
'   #            ', // 6
'                ', // 7
'                ', // 8
'                '  // 9
],[
'F::3            ', // 1
'H    F:::::7    ', // 2
'H    H     H    ', // 3
'H  F-*-7   H    ', // 4
'H  I****:::1    ', // 5
'L::x***1   H    ', // 6
'   I...J   H    ', // 7
'   H   F:7 L:::7', // 8
'   L:::J L:::::J'  // 9
]];
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.1, 100 );
camera.position.set( 2, 10, 25 );
var renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x111111, 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 );
var texture	= new THREE.TextureLoader().load( "brick.jpg" );
var material = new THREE.MeshBasicMaterial( { map: texture	, side: THREE.DoubleSide } );
var boxes = [];
var index = [];
var storeys = designBoxLabyrinth3D.length;

for( var f = 0; f < storeys; f ++ ) {

    for( var r = 0; r < designBoxLabyrinth3D[ f ].length; r ++ ) {

        for( var c = 0; c < designBoxLabyrinth3D[ f ][ r ].length; c ++ ) {

            boxes.push( createBox( designBoxLabyrinth3D[ storeys - 1 - f ][ r ][ c ] ) );

        }

    }

}

var labyrinthGeometry = THREE.BufferGeometryUtils.mergeBufferGeometries( boxes );
var labyrinthMesh = new THREE.Mesh( labyrinthGeometry, material );
scene.add( labyrinthMesh );
animate();

function animate() {

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

}

function createBox( icon ) {

    var g = new THREE.BoxBufferGeometry( );
    index = [];

    switch ( icon ) {

        case'G': box_G( );     break;
        case'M': box_M( );     break;
        case'C': box_C( );     break;
        case'3': box_3( );     break;
        case'U': box_U( );     break;
        case'H': box_H( );     break;
        case':': box_colon( ); break;
        case'F': box_F( );     break;
        case'7': box_7( );     break;
        case'L': box_L( );     break;
        case'J': box_J( );     break;
        case'I': box_I( );     break;
        case'1': box_1( );     break;
        case'-': box_minus( ); break;
        case'.': box_dot( );   break;
        case'*': box_multi( ); break;
        case'^': box_caret( ); break;
        case'v': box_v( );     break;
        case'x': box_x( );     break;
        case'#': box_sharp( ); break;
        default: box_x( );

    }

    g.setIndex( index );
    // position  c, f, r

    for ( let xidx = 0; xidx < 72; xidx += 3 ) {

        g.getAttribute('position').array[ xidx ] = g.getAttribute('position').array[ xidx ] + c;

    }

    for ( let yidx = 1; yidx < 72; yidx += 3 ) {

        g.getAttribute('position').array[ yidx ] = g.getAttribute('position').array[ yidx ] + f;

    }

    for ( let zidx = 2; zidx < 72; zidx += 3 ) {

        g.getAttribute('position').array[ zidx ] = g.getAttribute('position').array[ zidx ] + r;

    }

    return g;

}

function px( ) { index.push( 0, 2, 1, 2, 3, 1 ) }
function nx( ) { index.push( 4, 6, 5, 6, 7, 5 ) }
function py( ) { index.push( 8, 10, 9, 10, 11, 9 ) }
function ny( ) { index.push( 12, 14, 13, 14, 15, 13 ) }
function pz( ) { index.push( 16, 18, 17, 18, 19, 17 ) }
function nz( ) { index.push( 20, 22, 21, 22, 23, 21 ) }
function box_G( ) { px( ); nx( ); py( ); ny( ); pz( ); nz( ) }
function box_M( ) { px( ); nx( ); py( ); ny( ); nz( ) }
function box_C( ) { nx( ); py( ); ny( ); pz( ); nz( ) }
function box_3( ) { px( ); py( ); ny( ); pz( ); nz( ) }
function box_U( ) { px( ); nx( ); py( ); ny( ); pz( ) }
function box_H( ) { px( ); nx( ); py( ); ny( ) }
function box_colon( ) { py( ); ny( ); pz( ); nz( ) }
function box_F( ) { nx( ); py( ); ny( ); nz( ) }
function box_7( ) { px( ); py( ); ny( );  nz( ) }
function box_L( ) { nx( ); py( ); ny( ); pz( ) }
function box_J( ) { px( ); py( ); ny( ); pz( ) }
function box_I( ) { nx( ); py( ); ny( ) }
function box_1( ) { px( ); py( ); ny( ) }
function box_minus( ) { py( ); ny( ); nz( ) }
function box_dot( ) { py( ); ny( ); pz( ) }
function box_multi( ) { py( ); ny( ) };
function box_caret( ) { ny( ) }
function box_v( ) { py( ) }
function box_x( ) {  }
function box_sharp( ) { px( ); nx( ); pz( ); nz( ) }
</script>
</html>
 
16.11.2018  
 




HofK
Nun gibt es auch noch eine Variante mit einer selbst definierten BufferGeomety.

Das ist effizienter und es läßt sich Multimateial leicht einbringen.  [...] 



Weiterhin habe ich auf Anfrage eine Konvertierung von einer bestehenden 2D Verlies Definition zu meiner Design Notation erstellt.  [...] 
...
// dungeon 2D is subset of labyrinth 3D
var designDungeon2D = [// will be converted to labyrinth design 3D
' ##########  ',
' ###  ##  ##  ',
' ###  ###     ',
'## ## ########  ',
' ##### # #   #',
'   #  ## #####',
'   ####  #'
];



...
// convert "dungeon design 2D" style to "labyrinth3D" style
var storeys = 1; // like var storeys = designBoxLabyrinth3D.length;

var designBoxLabyrinth3D = [];
designBoxLabyrinth3D.push( [] );

var dRows = designDungeon2D.length;
var dCols;
var row;

for( var f = 0; f < storeys; f ++ ) {

for( var r = 0; r < dRows; r ++ ) {

dCols = designDungeon2D[ r ].length;
row = '';

for( var c = 0; c < dCols; c ++ ) {

row = row + convertDesignDungeon2D( designDungeon2D );

}

designBoxLabyrinth3D[ 0 ].push( row );

}

}

...

function convertDesignDungeon2D( dsgn ) {

var left = false;
var front = false;
var right = false;
var back = false;

if ( dsgn[ r ][ c ] === '#' ) {

if( c === 0 ) { left = true } else { if( dsgn[ r ][ c-1 ] !== '#' ) { left = true } };
if( r === 0 ) { front = true } else { if( dsgn[ r-1 ][ c ] !== '#' ) { front = true } };
if( c === dCols - 1 ) { right = true } else { if( dsgn[ r ][ c+1 ] !== '#' ) { right = true } };
if( r === dRows - 1 ) { back = true } else { if( dsgn[ r+1 ][ c ] !== '#' ) { back = true } };


if ( left && front && right && back ) return 'G';
if ( left && front && right && !back ) return 'M';
if ( left && front && !right && back ) return 'C';
if ( !left && front && right && back ) return '3';
if ( left && !front && right && back ) return 'U';
if ( left && !front && right && !back ) return 'H';
if ( !left && front && !right && back ) return ':';
if ( left && front && !right && !back ) return 'F';
if ( !left && front && right && !back ) return '7';
if ( left && !front && !right && back ) return 'L';
if ( !left && !front && right && back ) return 'J';
if ( left && !front && !right && !back ) return 'I';
if ( !left && !front && right && !back ) return '1';
if ( !left && front && !right && !back ) return '-';
if ( !left && !front && !right && back ) return '.';
if ( !left && !front && !right && !back ) return '*';

} else {
// elseif ( dsgn[ r ][ c ] === '.' )
return ' '; // String.fromCharCode(32); // space

}

}
 
22.11.2018  
 



 
- 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. [...] 

 
vor 31 Tagen  
 




p.specht
Gold-metallic: Besonders schwer darzustellen! Toll !
 
XProfan 11
So Computer sind halt auch nur Menschen...
vor 31 Tagen  
 




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>
 
vor 27 Tagen  
 




HofK
Pünktlich zu Sylvester.

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



von prisoner849 

 
vor 23 Tagen  
 




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.
 
vor 14 Tagen  
 




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>
 
vor 11 Tagen  
 




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>
 
vor 5 Tagen  
 




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.

 
vor 4 Tagen  
 




Antworten


Thementitel, max. 100 Zeichen.
 

Systemprofile:

Kein Systemprofil angelegt. [anlegen]

XProfan:

 Beitrag  Schrift  Smilies  ▼ 

Bitte anmelden um einen Beitrag zu verfassen.
 

Themenoptionen

46.542 Betrachtungen

Unbenanntvor 0 min.
WalterGestern (18:30)
Jörg SellmeyerGestern (10:26)
Peter Max MüllerGestern (04:45)
Manfred BareiVorgestern (23:04)
Mehr...

Themeninformationen



AGB  |  Chat  |  Datenschutz  |  Download  |  Eingangshalle  |  Hilfe  |  Impressum  |  Mart  |  Support  |  Suche

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