Skip navigation

Téglatest összetett mozgatása

Objektum hierarchia

Készítsük az alábbi modellezést!

  • Adjunk a színtérhez egy gömböt és egy kockát. Egyiküket a Z, másikukat az X tengely mentén toljuk el.
  • Adjunk a színtérhez egy AxesHelper objektumot is.
  • A gömb folyamatosan forogjon a Z-tengely körül. A kocka ne mozogjon.

A megoldást a 06_01_ThreeJsCubeSphereHierarchy.html program tartalmazza.

Módosítsuk az alábbi szerint.

A kocka hálót ne a színtérhez, hanem a gömb objektumhoz adjuk hozzá! Figyeljük meg a hatást!

var sphereGeometry = new THREE.SphereGeometry( 2, 20, 10 );
var sphereMaterial = new THREE.MeshBasicMaterial( { color: 0xffff00, wireframe: true } )
sphereMesh = new THREE.Mesh( sphereGeometry, sphereMaterial );
sphereMesh.position.set( 0, 0, 5 );
scene.add( sphereMesh );

var boxGeometry = new THREE.BoxGeometry( 2, 2, 2 );
var boxMaterial = new THREE.MeshBasicMaterial( { color: 0x00ff00, wireframe: true } )
boxMesh = new THREE.Mesh( boxGeometry, boxMaterial );
boxMesh.position.set( 8, 0, 0 );
sphereMesh.add( boxMesh );

Azt fogjuk tapasztalni, hogy a kocka elkezd forogni a gömb körül, a Z-tengely mentén. Mindezt anélkül, hogy a kockára bármilyen külön mozgást alkalmaztunk volna!

06_02_ThreeJsCubeSphereHierarchyPanel.html példaprogramban panelen kapcsolhatjuk, hogy a kocka gyermeke legyen-e a gömb modellnek, illetve hogy a gömb végezzen a forgást.

Object3D

Az objektumok egymásba ágyazását tetszőleges mélységig folytathatjuk. A gyerek objektumokra a szülők összes geometriai transzformációja hatással lesz. A gyerek objektumok a szülő koordináta-rendszerébe kerülnek, ahhoz képesti relatív helyzetüket adhatjuk meg. Több mélységnyi egymásba ágyazással összetett mozgások is megvalósíthatók.

Az egyetlen nagy probléma, hogy a szülő objektumok is megjelennek a színtérben. Ha a kockát ugyanígy szeretnénk forgatni (nem valamelyik főtengely körül), csak nem szeretnénk a szülő objektumot (gömböt) látni, erre is van megoldás. A Three.js Object3D objektumához nem tartozik megjelenő geometria, a geometriai transzformációit viszont állíthatjuk és adhatunk hozzá gyerek objektumokat. Ilyen objektumhoz nem kell anyagot és felszínhálót sem rendelni, közvetlenül a színtérhez adható!

Feladat

Módosítsuk úgy a programot, hogy a gömb helyett egy Object3D objektumot adjunk a színtérhez, és ehhez adódjon hozzá gyermekként a kocka. A szülő a gömb korábbi mozgását végezze!

Téglatest forgatása két tengely körül

A téglatestet a korábban megismert módon hozzuk létre. Úgy mozgatjuk, hogy az alsó lapja kerüljön az XZ síkra, valamint távolabb kerüljön az Y-tengelytől (XY-síktól).

geometryBox = new THREE.BoxGeometry( 100, 200, 100 );
material = new THREE.MeshBasicMaterial( { color: 0x333389, wireframe: false } );
meshBox = new THREE.Mesh( geometryBox, material );
meshBox.position.set( 0, 100, 250 );

Ha a meshBox objektumra alkalmazunk forgatást, az a saját hossztengelye mentén történik, mert végrehajtása sorrendileg megelőzi az eltolást. Ha az eltolás után szeretnénk a globális Y-tengely körül forgatni, akkor vegyünk fel egy új objektumot, amihez hozzáadjuk.

geometryHolder = new THREE.Object3D();
geometryHolder.add( meshBox );
scene.add( geometryHolder );

A geometryHolder objektumra alkalmazott forgatást a gyermek objektum is örökli, és a forgása a globális Y-tengely körül történik. Vagyis a gyermek objektum transzformációi a szülőhöz képest relatívan értelmezendők.

Vegyük észre, hogy elegendő csak a geometryHolder objektumot a színtérhez adni!

A forgást beállító renderelő kódrész (a ctrl a paraméterbeállító panel):

meshBox.rotation.y += ctrl.rotationObject;
if( ctrl.isGlobalRotation )
geometryHolder.rotation.y += 0.01;

Fényforrás mozgatása a kamerával együtt

A fenti példaprogramban azt is megfigyelhetjük, hogyan rögzíthetjük a fényforrásunkat a kamerához. Ezzel el tudjuk érni, hogy mindig a nézőpontunkból legyen megvilágítva a színtér. A főbb lépések az alábbiak:

  • A fényforrás pozícióját állítsuk (0, 0, 0)-ra.
  • A fényforrást a kamera objektumhoz adjuk gyermekként. Külön nem kell a színtérhez adni.
  • A kamera objektumot viszont adjuk hozzá a színtérhez.
    • Ezt eddig nem tettük, mert a kamera objektumot a renderer megkapja közvetlenül, valamint a kamera mozgásának nem volt következménye a színtér objektumaira vonatkozóan. Most van.
  • Ha reflektorfényt használunk, akkor ne felejtsünk el gondoskodni a célpont (target) megfelelő beállításáról sem!

Forráskód:

var pLight = new THREE.PointLight( 0xffffff, 1 );
pLight.position.set( 0, 0, 0 );
camera.add( pLight );
scene.add( camera );

Téglatest forgatása egyik éle és az Y-tengely körül

Az előző programot annyiban módosítjuk, hogy a téglatest a forgást ne a saját Y-tengelye, hanem az egyik éle körül végezze. Legyen ez a Z-tengely irányából nézve a bal hátsó függőleges él.

A szükséges transzformációs lépések:

  • Téglatest létrehozása (középpontja az origóban).
  • Eltolás, hogy a bal alsó sarka kerüljön az origóba (E1).
  • Forgatás az Y-tengely körül. Ez a bal hátsó él körüli forgást jelenti (F1).
  • Toljuk el a Z-tengely mentén egy adott távolságra (E2).
  • Forgassuk el így is az Y-tengely körül (F2).

A fenti sorozatot az alábbi módon tudjuk objektum hierarchiára alakítani:

boxMesh holder1 holder2
S, F, E (E1) S, F (F1), E (E2) S, F (F2), E

Az objektumok esetében skálázásra, forgatásra és eltolásra van lehetőség, ebben a rögzített sorrendben. A boxMesh így csak az E1 eltolást tudja ellátni. A holder1 az F1 forgatást és az E2 eltolást. Az F2 forgatáshoz egy újabb, holder2 objektum szükséges. A színtérhez a holder2-t adjuk. A holder1-et a holder2-höz, a boxMesh-t pedig a holder1-hez.

Algoritmus

Írjuk fel az (S, F, E) sorozatot, és balról jobbra haladva válasszuk ki a szükséges transzformációkat. Ha szükséges, vegyünk fel újabb Object3D objektumokat.

A konkrét megvalósítást a 06_04_ThreeJsBoxRotation2.html program mutatja.