PHP, HTML & JavaScript- Forum | | | | - Seite 1 - |
| ![HofK: 31.01.2016](.././../../i/a/1486.gif) HofK | Auf einen heißen Tipp von IF hin, habe ich mir mal three.js [...] angeschaut. Da [...] (ganz unten) die ersten Resultate. |
| | | | |
| | | | - Seite 46 - |
| | ![HofK: 05.12.2022](.././../../i/a/1486.gif) HofK | Auf der Basis obigen Rechtecks mit abgerundeten Ecken eine Variante einer Box.
Discourse: [...] UPDATE 2022: Github: [...] ![](/intl/i/lnk.gif)
![](https://xprofan.net/files/ievoo.png)
const geometry = RoundedBoxFlat( width, height, depth, radiusCorner, smoothness );
function RoundedBoxFlat( w, h, d, r, s ) {
const pi2 = Math.PI * 2;
const n = ( s + 1 ) * 4;// number of segments
let indices = [];
let positions = [];
let uvs = [];
makeFronts( n, 1, 0 );// segments, front is 1, start index 0 is center front
makeFronts( n, -1, n + 1 );// segments, back is -1, start index n + 1 is center back
makeFrame( n, 2 * n + 2, 1, n + 2 );// segments, start index framing ,start index front, start index back
const geometry = new THREE.BufferGeometry( );
geometry.setIndex( new THREE.BufferAttribute( new Uint32Array( indices ), 1 ) );
geometry.setAttribute('position', new THREE.BufferAttribute( new Float32Array( positions ), 3 ) );
geometry.setAttribute('uv', new THREE.BufferAttribute( new Float32Array( uvs ), 2 ) );
// add multimaterial groups for front, back, framing
const vtc = n * 3 ;// vertex count
geometry.addGroup ( 0, vtc, 0 );
geometry.addGroup ( vtc, vtc, 1 );
geometry.addGroup ( 2 * vtc, 2 * vtc + 3, 2 );
geometry.computeVertexNormals( );
return geometry;
function makeFronts( n, side, idx ) {
const d0 = side === 1 ? 0 : 1;
const d1 = side === 1 ? 1 : 0;
for ( let j = 1; j < n; j ++ ) {
indices.push( idx, idx + d0 + j, idx + d1 + j );
}
const d2 = side === 1 ? n : 1;
const d3 = side === 1 ? 1 : n;
indices.push( idx, idx + d2 , idx + d3 );
positions.push( 0, 0, side * d / 2 );// center
uvs.push( 0.5, 0.5 );
for ( let j = 0; j < n; j ++ ) {// contour
const qu = Math.trunc( 4 * j / n ) + 1 ;// quadrant qu: 1..4
const sgn = ( qu === 1 || qu === 4 ? 1: -1)// signum left/right
const c = { x: sgn * ( w / 2 - r ), y: ( qu < 3 ? 1 : -1 ) * ( h / 2 - r ), z: side * d / 2 }// quadrant center
const x = c.x + r * Math.cos( pi2 * ( j - qu + 1 ) / ( n - 4 ) );
const y = c.y + r * Math.sin( pi2 * ( j - qu + 1 ) / ( n - 4 ) );
const z = c.z;
positions.push( x, y, z );
const u0 = side === 1 ? 0 : 1;
uvs.push( u0 + side * ( 0.5 + x / w ), 0.5 + y / h );
}
}
function makeFrame( n, sidx, sif, sib ) {
let a, b, c, d, xf, yf, zf, xb, yb, zb;
const pif = sif * 3;// position start index front
const pib = sib * 3;// position start index back
let st = [];
let idx = sidx;
for ( let j = 0; j < n; j ++ ) {
a = idx;
b = idx + 1;
c = idx + 2;
d = idx + 3;
indices.push( a, b, d, a, d, c );
idx += 2;
}
for ( let j = 0; j < n ; j ++ ) {
const j3 = j * 3;
xf = positions[ pif + j3 ];
yf = positions[ pif + j3 + 1 ];
zf = positions[ pif + j3 + 2 ];
xb = positions[ pib + j3 ];
yb = positions[ pib + j3 + 1 ];
zb = positions[ pib + j3 + 2 ];
positions.push( xf, yf, zf, xb, yb, zb );
if ( j === 0 ) st = [ xf, yf, zf, xb, yb, zb ];// memorize
const v = j / n;// here only independent of section height
uvs.push( 0, v, 1, v );
}
positions.push( st[ 0 ], st[ 1 ], st[ 2 ], st[ 3 ], st[ 4 ], st[ 5 ] );// end = start
uvs.push( 0, 1, 1, 1 );
}
}
|
| | | | |
| | ![HofK: 09.12.2022](.././../../i/a/1486.gif) HofK | Noch eine weitere Variante, [...] ![](/intl/i/lnk.gif)
![](https://xprofan.net/files/covoo.png)
bei der man für die Textur auf der Umhüllung den Startpunkt auf einen beliebigen Quadranten legen kann. Bei den vorherigen Varianten waren die u Werte an des Start der Konstruktion gebunden und jeweils verschieden.
Dazu sind 4 zusätzliche Dreiecke zur vorherigen Variante und eine Doppelung der mittleren Punkte der Seiten erforderlich. Die Berechnung erfolgt quadrantenweise. Das gefällt mir sehr gut, da es übersichtlich ist.
![](https://xprofan.net/files/auvoo.png)
Ein anderer Startpunkt.
![](https://xprofan.net/files/vnkoo.png)
Github [...] ![](/intl/i/lnk.gif) Discourse [...] ![](/intl/i/lnk.gif)
-----------------------------------------------------------------------------------------
<!DOCTYPE html>
<!-- https://discourse.threejs.org/t/round-edged-box-flat/30012 -->
<head>
<title> RoundedBoxFlatUV </title>
<meta charset="utf-8" />
<style>
body { margin: 0; }
</style>
</head>
<body>
</body>
<script type="module">
// @author hofk
import * as THREE from "../jsm/three.module.132.js";
import { OrbitControls } from "../jsm/OrbitControls.132.js";
const scene = new THREE.Scene( );
const camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.01, 10000 );
camera.position.set( 4, 12, 12 );
const renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xdedede, 1 );
const container = document.createElement('div' );
document.body.appendChild( container );
container.appendChild( renderer.domElement );
const axesHelper = new THREE.AxesHelper( 10 );
scene.add( axesHelper );
const controls = new OrbitControls( camera, renderer.domElement );
const texturLoader = new THREE.TextureLoader( );
const material = [
new THREE.MeshBasicMaterial( { map: texturLoader.load('uvgrid01.png' ), wireframe: false} ),
new THREE.MeshBasicMaterial( { map: texturLoader.load('uv_grid_opengl.jpg' ), wireframe: false} ),
new THREE.MeshBasicMaterial( { map: texturLoader.load('uvgrid01.png' ), wireframe: false } ),
];
// const material =new THREE.MeshBasicMaterial( { color: 'black', wireframe: true } );
const width = 5;
const height = 4;
const depth = 9;
const radiusCorner = 1;
const smoothness = 4;
const uStartQuadr = 2;// tart quadrant regarding u, default is 1
const geometry = RoundedBoxFlat( width, height, depth, radiusCorner, smoothness, uStartQuadr );// uStartQuadr optional
geometry.computeVertexNormals( );
const mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
animate( );
function animate( ) {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
function RoundedBoxFlat( w, h, d, r, s, q ) {
let qu = q || 1;// qu: start quadrant regarding u, optional
const pi = Math.PI;
let indices = [];
let positions = [];
let uvs = [];
makeFronts( s, 1, 0 );// smoothness, front is 1, start index center front
makeFronts( s, -1, 4 * ( s + 3 ) + 1 );// smoothness, back is -1, start index center back
makeFrame( s, 2 * ( 4 * ( s + 3 ) + 1 ), 1, 4 * ( s + 3 ) + 2 );// smoothness, start index framing ,start index front, start index back
const geometry = new THREE.BufferGeometry( );
geometry.setIndex( new THREE.BufferAttribute( new Uint32Array( indices ), 1 ) );
geometry.setAttribute('position', new THREE.BufferAttribute( new Float32Array( positions ), 3 ) );
geometry.setAttribute('uv', new THREE.BufferAttribute( new Float32Array( uvs ), 2 ) );
// add multimaterial groups for front, back, framing
const vtc = 4 * ( s + 2 ) * 3;
geometry.addGroup ( 0, vtc, 0 );
geometry.addGroup ( vtc , vtc, 1 );
geometry.addGroup ( 2 * vtc, 2 * vtc + 3, 2 );
geometry.computeVertexNormals( );
return geometry;
function makeFronts( s, side, idx ) {
const d0 = side === 1 ? 0 : 1;
const d1 = side === 1 ? 1 : 0;
let id = 0;
for ( let q = 1; q < 5; q ++ ) {// quadrants
id ++;
for ( let j = 0; j < s + 2; j ++ ) {
indices.push( idx, idx + d0 + id, idx + d1 + id );
id ++;
}
}
positions.push( 0, 0, side * d / 2 );// center
uvs.push( 0.5, 0.5 );
let x, y, z, sgnX, sgnY;
let phi = 0;
const u0 = side === 1 ? 0 : 1;
for ( let q = 1; q < 5; q ++ ) {
sgnX = q === 1 || q === 4 ? 1 : -1;
sgnY = q < 3 ? 1 : -1 ;
x = Math.cos( phi ) * w / 2;
y = Math.sin( phi ) * h / 2;
z = side * d / 2;
positions.push( x, y, z );
uvs.push( u0 + side * ( 0.5 + x / w ), 0.5 + y / h );
for ( let j = 0; j < s + 1; j ++ ) {
const c = { x: sgnX * ( w / 2 - r ), y: sgnY * ( h / 2 - r ), z: side * d / 2 }// quadrant center
const dPhi = pi / 2 * j / s;
x = c.x + r * Math.cos( phi + dPhi );
y = c.y + r * Math.sin( phi + dPhi );
z = c.z;
positions.push( x, y, z );
uvs.push( u0 + side * ( 0.5 + x / w ), 0.5 + y / h );
}
phi = phi + pi / 2;
x = Math.cos( phi ) * w / 2;
y = Math.sin( phi ) * h / 2;
z = side * d / 2;
positions.push( x, y, z );
uvs.push( u0 + side * ( 0.5 + x / w ), 0.5 + y / h );
}
}
function makeFrame( s, sidx, sif, sib ) {
let a, b, c, d, xf, yf, zf, xb, yb, zb;
const pif = sif * 3;// position start index front
const pib = sib * 3;// position start index back
let idx = sidx;
for ( let q = 1; q < 5; q ++ ) {
for ( let j = 0; j < s + 2; j ++ ) {
a = idx;
b = idx + 1;
c = idx + 2;
d = idx + 3;
indices.push( a, b, d, a, d, c );
idx += 2;
}
idx += 2;
}
const ls = 2 * r * Math.sin( pi / ( s * 4 ) );// length of the outer line of a corner segment
const w2r = w / 2 - r;
const h2r = h / 2 - r;
const peri = 4 * w2r + 4 * h2r + 4 * s * ls;// perimeter
let u;
idx = 0;// reset
for ( let q = 1; q < 5; q ++ ) {
// console.log ( 'qu', qu );
u = qu / 4;
for ( let j = 0; j < s + 3; j ++ ) {
xf = positions[ pif + idx ];
yf = positions[ pif + idx + 1 ];
zf = positions[ pif + idx + 2 ];
xb = positions[ pib + idx ];
yb = positions[ pib + idx + 1 ];
zb = positions[ pib + idx + 2 ];
positions.push( xf, yf, zf, xb, yb, zb );
idx += 3;
// console.log ( 'u ', u );
uvs.push( u , 0, u, 1 );
if ( j === 0 ) { u -= q === 1 || q === 3 ? h2r / peri : w2r / peri; }
if ( j === s + 1 ) { u -= q === 1 || q === 3 ? w2r / peri : h2r / peri; }
if ( j > 0 && j < s + 1 ) { u -= ls / peri; }
}
qu = 4 - ( ( 5 - qu ) % 4 );// cyclic next quadrant with respect to u
}
}
}
</script>
</html>
|
| | | | |
| | ![HofK: 21.12.2022](.././../../i/a/1486.gif) HofK | Eine weitere Figur,die ich im Netz verwenden werde. Sie ist aus losen Punkten zusammengesetzt.
[...] ![](/intl/i/lnk.gif)
Github [...] ![](/intl/i/lnk.gif)
<!DOCTYPE html>
<!-- https://discourse.threejs.org/t/create-circle-with-fuzzy-edge-made-of-individual-random-particles/30150/9 -->
<head>
<title> SphereWithRandomPointsl </title>
<meta charset="utf-8" />
<style>
body{
overflow: hidden;
margin: 0;
}
</style>
</head>
<body> </body>
<script type="module">
// @author hofk
import * as THREE from'../jsm/three.module.135.js';
import { OrbitControls} from'../jsm/OrbitControls.135.js'
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera( 60, innerWidth / innerHeight, 0.001, 100);
camera.position.set( 1, 1, 2 );
let renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
renderer.setClearColor( 0xdedede, 1 );
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", (event) => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
});
let controls = new OrbitControls(camera, renderer.domElement);
let helper = new THREE.AxesHelper( );
scene.add( helper );
const n = 25000;// points count
const dri = 0.07;// radius inner difference
const r = 0.6;// radius main
const dro = 0.4;// radius outer difference
const geometry = PointsSphere( n, dri, r, dro );
const pointsMaterial = new THREE.PointsMaterial( { size: 0.01, color: 0xff00ff } );
const spherePoints = new THREE.Points( geometry, pointsMaterial );
scene.add( spherePoints );
renderer.setAnimationLoop( ( ) => { renderer.render(scene, camera); } );
// .....................................
function PointsSphere( n, dri, r, dro ) {
// n: points count, dri: inner difference , r: radius main, dro: outer difference
const pts = [];
for( let i = 0; i < n ; i++){
const inout = ( Math.random( ) - 0.5 ) * 2;
const lim = ( inout >= 0 ? dro : dri );
const rand = r + Math.pow( Math.random( ), 3 ) * lim * inout;
const θ = Math.PI * 2 * Math.random( );
const φ = Math.acos( 2 * Math.random( ) - 1 );
const ps = new THREE.Vector3( Math.cos( θ ) * Math.sin( φ ), Math.sin( θ ) * Math.sin( φ ), Math.cos( φ ) );
pts.push( ps.multiplyScalar( rand ) );
}
const geometry = new THREE.BufferGeometry( ).setFromPoints( pts );
return geometry;
}
</script>
</html>
|
| | | | |
| | ![HofK: 15.01.2023](.././../../i/a/1486.gif) HofK | ![](https://xprofan.net/files/ucioo.png)
Ein Jahr ist wieder vorüber und die gesammelten Beispiele von Discourse stehen seit einigen Tagen zum Download bereit. [...] ![](/intl/i/lnk.gif) |
| | | | |
| | ![HofK: 10.02.2023](.././../../i/a/1486.gif) HofK | Bei der Arbeit am Netz hatte ich ein Problem mit der Transparenz. Je nach Kameraposition verschwanden die transparenten Flügel der Biene in der transparenten Blase.
Transparenz gemischt ist ein oftmals schwieriges Problem. In meinem Fall gab es eine einfache Lösung - einfach, wenn man es dann kennt.
Discourse: [...] ![](/intl/i/lnk.gif)
Seite in der Sammlung mit Lösung: [...] ![](/intl/i/lnk.gif)
![](https://xprofan.net/files/uuioo.png) |
| | | | |
| | ![HofK: 15.02.2023](.././../../i/a/1486.gif) HofK | Eine neue spezielle Geometrie:
Dynamisches Mondphasen Panel
![](https://xprofan.net/files/anaoo.png)
Siehe unter Github [...] ![](/intl/i/lnk.gif)
<!DOCTYPE html>
<!-- https://discourse.threejs.org/t/addon-to-create-special-extended-geometries/1855/12 -->
<head>
<title> MoonPhases </title>
<meta charset="utf-8" />
<style>
body{
overflow: hidden;
margin: 0;
}
</style>
</head>
<body></body>
<script type="module">
// @author hofk
import * as THREE from "../jsm/three.module.149.js";
import { OrbitControls } from "../jsm/OrbitControls.149.js";
const scene = new THREE.Scene( );
const camera = new THREE.PerspectiveCamera( 55, innerWidth / innerHeight, 0.01, 1000 );
camera.position.set( 0, 1, 4 );
const renderer = new THREE.WebGLRenderer( );
renderer.setSize( innerWidth, innerHeight );
renderer.setClearColor( 0xdedede );
document.body.appendChild(renderer.domElement);
const pointLight1 = new THREE.PointLight( 0xffff00, 1.1 );
pointLight1.position.set( 1, 2, 7 );
scene.add( pointLight1 );
const pointLight2 = new THREE.PointLight( 0xffff00, 1.1 );
pointLight2.position.set( -1, -2, -7 );
scene.add( pointLight2 );
new OrbitControls( camera, renderer.domElement );
const material = new THREE.MeshPhongMaterial( { color: 0xfbfb23, wireframe: true, side: THREE.DoubleSide } );
const moonGeo = MoonPhases( 1, 0.2, 32, 0 );
const moon = new THREE.Mesh( moonGeo, material );
scene.add( moon );
let t = 0;
animate( );
function animate( ) {
t += 0.01;
requestAnimationFrame( animate );
moonGeo.calculatePositions( t );// phase dynamic
renderer.render( scene, camera );
}
function MoonPhases( radius, depth, heightSegments, phase ) {
const g = new THREE.BufferGeometry( );
const pi = Math.PI;
const pi2 = pi * 2;
const hs2 = heightSegments * 2;// equals triangles per side
const phs = phase || 0.1;
let indices = [];
let φ;
let ib;// index back
for ( let i = 0; i < hs2; i += 2 ) {
indices.push( i, i + 2, i + 1, i + 1, i + 2, i + 3 );// front
}
for ( let i = 0; i < hs2; i += 2 ) {
ib = i + hs2 + 2;
indices.push( ib, ib + 1, ib + 2, ib + 1, ib + 3, ib + 2 );// back
}
for ( let i = 0; i < hs2; i += 2 ) {
ib = i + hs2 + 2;
indices.push( i, ib, ib + 2, i, ib + 2, i + 2 );// framing right
indices.push( ib + 1, i + 1, i + 3, ib + 1, i + 3, ib + 3 );// framing left
}
const sidePosCount = ( heightSegments + 1 ) * 2 ;
g.setIndex( new THREE.BufferAttribute( new Uint32Array( indices ), 1 ) );
g.setAttribute('position', new THREE.BufferAttribute( new Float32Array( sidePosCount * 2 * 3 ), 3 ) );
g.calculatePositions = function( t ) {
t = t % pi2;
const leftEdge = t => t < pi ? Math.cos( t ) : -1;
const rightEdge = t => t < pi ? 1 : -Math.cos( t );
φ = 0;
for ( let i = 0; i < sidePosCount; i += 2 ) {
// front
g.attributes.position.setXYZ( i , radius * rightEdge( t ) * Math.sin( φ ), -radius * Math.cos( φ ), depth / 2 );
g.attributes.position.setXYZ( i + 1, radius * leftEdge( t ) * Math.sin( φ ), -radius * Math.cos( φ ), depth / 2 );
// back
ib = i + hs2 + 2;
g.attributes.position.setXYZ( ib , radius * rightEdge( t ) * Math.sin( φ ), -radius * Math.cos( φ ), -depth / 2 );
g.attributes.position.setXYZ( ib + 1, radius * leftEdge( t ) * Math.sin( φ ), -radius * Math.cos( φ ), -depth / 2 );
φ += pi / heightSegments;
}
g.attributes.position.needsUpdate = true;
g.computeVertexNormals( );
}
g.calculatePositions( phs * pi2 );
return g;
}
</script>
</html>
|
| | | | |
| | ![p.specht: 15.02.2023](.././../../i/a/3477.gif) p.specht
![DOKTOR XPROFAN EHRENHALBER](.././../../i/dr.gif) | (Off Topic Mit welchem Programm werden eigentich diese Hochglanz-Werbefilme erzeugt, wo glänzende Materialien wie Apfelsaft oder Schokolade dynamisch in Behälter strömen? |
| | | XProfan 11Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen, zB 'daß' statt 'das'... | 15.02.2023 ▲ |
| |
| | ![HofK: 24.02.2023](.././../../i/a/1486.gif) HofK | p.specht (15.02.2023)
(Off Topic Mit welchem Programm ...
Da gibt es eine Reihe sehr professioneller Software. Die Preise sind nichts für privat.
Und Firmen wie z.B. Mynd ( mal googeln) nutzen sicher verschiedene solcher Systeme. |
| | | | |
| | ![HofK: 24.02.2023](.././../../i/a/1486.gif) HofK | Vor einem Jahr habe ich an einer prozedural erzeugten Figur gearbeitet. Siehe weiter oben. Allerdings habe ich das nur als Studie gemacht und nicht komplett ausgearbeitet.
Ich bin jetzt auf eine recht professionelle und frei verfügbare Variante gestoßen. Sie arbeitet ohne Skelett, benutzt aber auch Kugelgelenke.
Siehe Github: [...] ![](/intl/i/lnk.gif)
Ich habe sie erfolgreich in mein derzeitiges Projekt integriert.
Die README ist vom Autor sehr umfangreich bebildert und mit Live-Beispielen versehen.
Dieser dynamische Kerl ist sehenswert.
![](https://xprofan.net/files/vmaoo.png) |
| | | | |
| | ![HofK: 01.04.2023](.././../../i/a/1486.gif) HofK | Ein weiteres paralleles Projekt erfordert Zeit und lässt wenig übrig.
![](https://xprofan.net/files/kmuoo.png)
Ein Fehler zeigte, dass bei komplexen Rechnungen die Präzision zum Problem werden kann. Siehe [...] ![](/intl/i/lnk.gif)
![](https://xprofan.net/files/mcuoo.png)
Es gab eine glänzende Analyse von PavelBoytchev, der in letzter Zeit sehr viele professionelle Lösungen auf Fragen im Forum postet. Immer mit sehr gut dokumentierten Codepens. Da ich mit der Sammlung aus Zeitgründen nicht hinterher komme, habe ich in der Sammlung Links zu [...] und auch zu [...] hinzugefügt.
![](https://xprofan.net/files/ocuoo.png) |
| | | | |
| | ![HofK: 20.06.2023](.././../../i/a/1486.gif) HofK | Mittlerweile habe ich eine stabile Grundkonstruktion für das Projekt.
![](https://xprofan.net/files/aivnu.png)
Allerdings war es nicht so einfach wie gedacht.
Eine Frage bei discourse brachte mich etwas weiter [...] ![](/intl/i/lnk.gif)
Dabei eine schwer verdauliche Quelle, die Pavel Boytchev für mich sinnvoll fand. Ich habe sie umgangen, siehe discourse ! |
| | | | |
| | ![HofK: 30.12.2023](.././../../i/a/1486.gif) HofK | Wie schnell die Zeit vergeht. ![](.././../../i/s/time.gif)
Seit dem letzten Beitrag ist nun bereits ein halbes Jahr vergangen.
Das parallele Projekt ist eine kommerzielle Sache und daher muß das vorherige open source Projekt pausieren.
Das Projekt wird umfangreicher als zunächst angedacht, denn um die Geometrien sinnvoll erzeugen zu können brauchte es noch einen speziellen web-Editor. Die Sache ist noch in Arbeit.
Nebenbei bin ich gerade mal dazu gekommen zum Jahresende die Sammlung der Beispiele von discourse zu vervollständigen. Da gibt es viele interessante Beispiele.
Insbesondere Pavel Boytchev ( Researcher and educator Faculty of Mathematics and Informatics, Sofia University ) hat sehr viele lehrreiche Beiträge mit Beispielen im Forum verfasst.
Siehe [...] ![](/intl/i/lnk.gif)
Auch auf seiner Seite [...] finden sich interessante Beispiele. Auch reines WebGL ohne three.js. |
| | | | |
|
AntwortenThemenoptionen | 324.642 Betrachtungen |
ThemeninformationenDieses Thema hat 10 Teilnehmer: |