Pontfelhő geometria és anyag
Térbeli koordináta megadása
A legegyszerűbb geometria a térbeli pont, amit X, Y és Z koordinátáival tudunk megadni. A példánkban mindhárom koordináta véletlenszerűen kap értéket a [-1000, 1000] intervallumból (a kamera paramétereit ennek megfelelően állítjuk be). A koordináta értékeket egy vertices nevű JavaScript tömbhöz adjuk. A tömbhöz tetszőleges számú további koordináta hármast hozzáadhatunk további push() függvényhívásokkal.
let vertices = [];
vx = Math.random() * 2000 - 1000;
vy = Math.random() * 2000 - 1000;
vz = Math.random() * 2000 - 1000;
vertices.push( vx, vy, vz );
JavaScript tömb helyett közvetlenül Float32Array típusolt tömböt is létrehozhatunk és indexeléssel adhatunk értéket az elemeknek. Az alábbi példában 10000 darab csúcspontot hozunk létre véletlenszerű koordináta értékekkel. For ciklussal járjuk be a tömböt, figyelve az indexelés helysségére. A típusolt tömb létrehozásakor figyelni kell arra, hogy hány darab értékkel szeretnénk használni. Egy csúcsponthoz 3 koordináta érték tartozik, így 30000 darab float értékre lesz szükségünk. A korábban leírtak szerint érdemes külön változókat létrehoznunk az egyes egységek darabszámaira és azokat használni a kód megfelelő részén, hogy változás esetén csak egy helyen kelljen módosítani.
// Ponthalmaz
let particleCount = 10000;
let particlePositionAttributeSize = 3;
let vertices = new Float32Array( particleCount * particlePositionAttributeSize );
for( let i = 0, idx = 0; i < particleCount; i++, idx += particlePositionAttributeSize ) {
vertices[ idx ] = Math.random() * 2000 - 1000; // vx
vertices[ idx + 1 ] = Math.random() * 2000 - 1000; // vy
vertices[ idx + 2 ] = Math.random() * 2000 - 1000; // vz
}
Puffer attribútum tömb beállítása
A következő lépésben létrehozzuk a BufferGeometry objektumot és átadjuk pozíció attribútumként az előző lépésben létrehozott típusolt tömböt.
// Geometria létrehozása + attribútum beállítása
let particlesGeometry = new THREE.BufferGeometry();
particlesGeometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, particlePositionAttributeSize ) );
THREE.PointsMaterial
A ponthalmazok megjelenítését egy külön anyag, a PointsMaterial írja le. A konstruktornak egy paraméterhalmazt adhatunk át, de utólagosan is módosíthatjuk az attribútumokat a nevük segítségével.
color | Pontok megjelenítési színe. Alapértelmezés a fehér (0xffffff) szín. Figyeljünk arra, hogy amennyiben a vertexColors true értékű, akkor egyrészt létre kell hoznunk egy szín tömböt a csúcspontokhoz, és a BufferGeometry objektumnak 'color' attribútumként be kell állítanunk. Másrészt az anyagnál megadott color értékkel a színértékeket komponensenként összeszorozza! Ha a tömbben beállított színeket szeretnénk látni, akkor figyeljünk arra, hogy a color a maximális fehér színű legyen. |
size | Pontok megjelenő mérete a raszteres képmátrixban. Alapérték 1.0. |
sizeAttenuation | Logikai érték, a kamerától való távolság befolyásolja-e a pont képernyőn megjelenő méretét? Alapértelmezés a true. |
vertexColors |
A Three.js r114 verzió óta logikai érték. Alapértéke false (minden pont az anyaghoz beállított color attribútum színét kapja), true esetén minden ponthoz külön színt rendelhetünk, ami a geometria objektum color attribútumaként kell minden csúcsponthoz megadásra kerüljön. Korábbi Three.js verziókban THREE.NoColors (alapértelmezés, minden pont az anyag color attribútum színét kapja), THREE.FaceColors, és THREE.VertexColors értékeket vehetett fel. |
fog | Ködhatás befolyásolja-e a pont színét? (A távolság növekedésével halványuljon-e a szín?) |
map | A pontok a színüket egy betöltött kép alapján kapják. Ezzel itt nem foglalkozunk. |
Használati példa
let particlesMaterial = new THREE.PointsMaterial( { size: 2, color: 0xa0a000, sizeAttenuation: true } );
Minden ponthoz külön szín rendelése
A 04_01_c_ThreeJsPoints_VertexColors.html példaprogramban láthatunk konkrét példát, amit lentebb részletezünk.
Dokumentáció
Pontfelhő objektum
Az előkészített geometriából és anyagból hozhatjuk létre a pontfelhő objektumot, amit a színtérhez adhatunk.
particles = new THREE.Points( particlesGeometry, particlesMaterial );
scene.add( particles );
Dokumentáció
Megjegyzések
- Korábbi Three.js verziókban a THREE.Points neve THREE.PointCloud, a THREE.PointsMaterial pedig THREE.PointCloudMaterial volt! A régi példaprogramok kódjában ezt módosítani kell.
- Ha a pontfelhő objektum létrehozása után módosítunk a koordináta vagy szín adatokon, akkor azt jelezni kell a rendszernek a felszínháló objektum verticesNeedUpdate(), illetve colorsNeedUpdate() függvényhívásaival!
Egyszínű pontfelhő példaprogram
- Létrehozunk egy 10.000 pontból álló felhőt, amely sárga színű pontokból fog állni.
- A rendereléskor az X- és Y-tengelyek körül folyamatosan elforgatjuk.
- Az egér mozgatásával a kamera pozícióját módosíthatjuk.
- Megjelenítünk az origóban egy kék színű gömb drótvázat, ami szintén folyamatos forgást végez.
Teendők
- Változtassuk a ponthalmaz számosságát!
- Változtassuk a pont anyag paramétereit!
A 04_01_a_ThreeJsPoints_JS_array.html példaprogram JavaScript tömbök használatával oldja meg a feladatot. A 04_01_b_ThreeJsPoints_Float32Array.html példaprogramban közvetlenül Float32Array tömböt hozunk létre.
Pontfelhő pontonkénti színezése példaprogram
A pontfelhő egyenkénti színezését a 04_01_c_ThreeJsPoints_VertexColors.html példaprogramban láthatjuk. A kapcsolódó kódrész az alábbi.
// Ponthalmaz
let particleCount = 10000;
let particlePositionAttributeSize = 3; // X, Y, Z
let particleColorAttributeSize = 3; // R, G, B
let vertices = new Float32Array( particleCount * particlePositionAttributeSize );
let vertexColors = new Float32Array( particleCount * particleColorAttributeSize );
for( let i = 0, idx = 0; i < particleCount; i++, idx += 3 ) {
vertices[ idx ] = Math.random() * 2000 - 1000; // vx
vertices[ idx + 1 ] = Math.random() * 2000 - 1000; // vy
vertices[ idx + 2 ] = Math.random() * 2000 - 1000; // vz
vertexColors.set( [ Math.random(), Math.random(), Math.random() ], idx ); // R, G, B
}
// Geometria létrehozása + attribútumok beállítása
let particlesGeometry = new THREE.BufferGeometry();
particlesGeometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, particlePositionAttributeSize ) );
particlesGeometry.setAttribute( 'color', new THREE.BufferAttribute( vertexColors, particleColorAttributeSize ) );
let particlesMaterial = new THREE.PointsMaterial( { size: 2, color: 0xffffff, vertexColors: true, sizeAttenuation: true } );
particles = new THREE.Points( particlesGeometry, particlesMaterial );
scene.add( particles );
A vertexColors tömböt a Three.js implementációja Float32Array-ként várja, a színcsatornák intenzitását [0, 1] tartományban megadva. A szín tömböt 'color' attribútumként adjuk át. Figyelni kell arra, hogy az anyag objektumnál a vertexColors attribútum true értékű legyen, illetve a color attribútumát 0xffffff-re állítsuk. Próbáljuk ki, mi történik, ha más értéket adunk meg itt!
Demó program
A https://codepen.io/seanseansean/pen/EaBZEY helyen található demó program adaptálása a saját keretünkbe. Megnyitható önálló ablakban (04_02_ThreeJsPointsDemo).
Öt véletlenszerűen generált, egyenként 20.000 pontból álló felhő létrehozása és az idő előrehaladásával változó módon való forgatása és színváltása. Az egér mozgatásával a kamera pozícióját módosíthatjuk.