Přestože se některým z vás může titulek tohoto článku zdát nesmyslný, Java skutečně umí pracovat s 3D grafikou. Málokdo totiž ví, že pro Javu existuje API, které je distribuováno jako volitelný balíček (není tedy součástí standardní distribuce). Že je možné pomocí něj vytvářet poměrně zajímavé věci, o tom vás snad přesvědčí následující série článků.

Java 3D API umožňuje pomocí vysokoúrovňových konstrukcí vytvářet rozličné scény s texturami, světly nebo třeba mlhou. Poskytuje elegantní mechanismy pro animování scén a pro definování „chování“ objektů. Spolu s téměř dokonalým naplněním javovského paradigmatu „Write once, run anywhere“ (jednou napiš, spusť kdekoliv) se jedná o velmi silný nástroj. Pro Windows a Solaris existují implementace přímo od společnosti Sun. Linuxová komunita, jak už se stává pomalu zvykem, si pomohla sama a portovala API na svou platformu, stejně tak však učinily i další firmy, například HP pro HP-UX nebo IBM pro Irix.

Sunovská SDK pro Javu 3D ve verzích pro Windows a Solaris si můžete stáhnout z http://java.sun.com/products/java-media/3D/download.html, odkud je možné získat rovněž dokumentaci. SDK pro Linux najdete na http://www.blackdown.org/java-linux/jdk1.2-status/java-3d-status.html. Rovněž se vám může hodit oficiální tutorial, který naleznete na http://java.sun.com/products/java-media/3D/collateral/

Zbývá ještě poznamenat, že k Java 3D API existují i alternativy pocházející ze světa Open Source. Patří mezi ně například xith3D, který je ale zatím jen v alpha verzi. Je však docela možné, že se právě využívání xith3D nebo nějakého jiného Open Source API v budoucnu stane hlavní cestou, kterou se bude ubírat psaní 3D aplikací v Javě. Není totiž příliš jasné, co se s Javou 3D bude dít, protože Sun o její budoucnosti zatím zlověstně mlčí. Na druhou stranu není příliš realistická ani představa, že by někdy v dohledné době Java 3D jako taková přestala být podporována. To si Sun prostě nemůže dovolit, neboť by tím značně utrpěla jeho pověst (Java 3D je využíváno například univerzitami pro vizualizaci vědeckých výpočtů). Přesunem vývoje Java 3D API do oblasti Open Source by se vlk nažral a koza by zůstala celá. Jedná se ale samozřejmě pouze o spekulaci.

Základní principy psaní 3D programů v Javě

Základem každé scény v Javě 3D je objekt VirtualUniverse, který určitým způsobem odkazuje (ať už přímo nebo nepřímo) na všechny ostatní objekty, které se ve scéně objeví. Používání třídy VirtualUniverse však není příliš obvyklé, mnohem častěji je,alespoň u jednodušších programů, používána třída SimpleUniverse, což je podtřída třídy VirtualUniverse, jejíž využívání je mnohem snazší a většinou zcela dostačující. Zbavuje nás totiž nutnosti starat se o objekty PhysicalBody, PhysicalPlatform, View a ViewPlatform. (Jejich účelem se nyní zabývat nebudeme, zatím bychom se tím pouze zbytečně zdržovali.

Všechny objekty ve scéně dohromady vytvářejí stromovou strukturu, jejímž kořenem je právě VirtualUniverse, který odkazuje na objekt Locale, což je zhruba řečeno počátek souřadné soustavy scény. Objekt Locale pak odkazuje na objekty BranchGroup, což jsou kořeny jednotlivých částí scény a také té části stromu (nebo též grafu scény, chcete-li), která obsahuje objekty sloužící k zobrazování scény, tj. PhysicalBody, PhysicalPlatform, View a ViewPlatform. Jak jsme si ale řekli dříve, těmito objekty se zabývat nebudeme, neboť si zatím vystačíme pouze s využíváním třídy SimpleUniverse.

Vše bude mnohem jasnější, ukážeme-li si kód pro vytvoření úplně jednoduché scény s jediným zobrazovaným objektem, jímž bude objekt ColorCube. Třída ColorCube je svým způsobem velmi kuriózní a jediné, co může ospravedlňovat její existenci, je její časté využívání v programech typu HelloWorld, ne nepodobných tomu našemu. Třída ColorCube totiž definuje krychli, jejíž každá strana má jinou barvu a jediné, co u ní můžete změnit, je její velikost.

import java.awt.*;
import javax.swing.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;
import javax.media.j3d.*;
public class BarevnaKrychle extends JFrame{
public BarevnaKrychle() {
    super(„Barevná krychle“);
    setSize(400,400);
    Container pane = getContentPane();
    pane.setLayout(new BorderLayout());
    //získáme objekt GraphicsConfiguration, který budeme potřebovat při vytváření
    //nové instance třídy Canvas3D
    GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
    //vytvoříme Canvas3D
    Canvas3D canvas = new Canvas3D(config, false);
    //vložíme Canvas3D do našeho JFrame
    pane.add(„Center“, canvas);
    //vytvoříme nový SimpleUniverse
    SimpleUniverse universe = new SimpleUniverse(canvas);
    //vytvoříme objekt BranchGroup, který bude sloužit jako
    //kořen pro naši krychli
    BranchGroup rootKrychle = new BranchGroup();
    //vytváříme barevnou krychli a přidáváme ji jako následníka
    //do objektu rootKrychle
    rootKrychle.addChild(new ColorCube(0.3));
    //metodě compile se budeme věnovat později
    rootKrychle.compile();
    //nastavíme vzdálenost pozorovatele od obrazovky na 2 metry
    universe.getViewingPlatform().setNominalViewingTransform();
    //přidáme část grafu s krychlí do stromu (grafu)
    universe.addBranchGraph(rootKrychle);
    addWindowListener(new java.awt.event.WindowAdapter() {
       public void windowClosing(java.awt.event.WindowEvent evt) {
       System.exit(0);
       }
    });
}
public static void main(String args[]){
    new BarevnaKrychle().show();
}
}

Výsledný obrázek:

pohled na vytvořenou krychli ze předu

Červený čtverec uprostřed, ačkoli to není snadné poznat, je naše barevná krychle, kterou vidíme zepředu. Nic moc, chce se říci. Takže si pojďme scénu trochu upravit. Postačí ji pouze trochu otočit.

TransformGroup transformGroup = new TransformGroup();
//vytvoříme první transformační matici
Transform3D tr1 = new Transform3D();
//nastavíme úhel otočení na 30°
tr1.rotX(Math.PI/6);
//vytvoříme druhou transformační matici
Transform3D tr2 = new Transform3D();
//nastavíme úhel otočení na 60°
tr2.rotY(Math.PI/3);
//vynásobíme spolu matice
tr2.mul(tr1);
//nastavíme v objektu TransformGroup transformační matici na naši matici
transformGroup.setTransform(tr2);
//přidáme TransformGrou jako následníka do objektu BranchGroup rootKrychle
rootKrychle.addChild(transformGroup);
//vytváříme barevnou krychli a přidáváme ji jako následníka
//do objektu transformGroup
transformGroup.addChild(new ColorCube(0.3));

Výsledek vypadá následovně:

pohled na vytvořenou krychli (2)

Otočení zajišťuje objekt TransformGroup, který jsme vložili jako další uzel mezi objekt BranchGroup a krychli, kterou jsme chtěli otočit. K vytvoření výsledné transformační matice bylo zapotřebí vytvořit nejprve jeden objekt Transform3D, který reprezentoval otočení kolem osy x, poté druhý objekt Transform3D, jenž pro změnu obsahoval složku pro otočení kolem osy y, a tyto dvě matice reprezentované objekty Transform3D pak vynásobit. Nakonec jsme ještě museli nastavit pomocí takto získané matice objekt TransformGroup.

Tím bychom pro tentokrát skončili. Příště nás čeká podrobnější exkurz do problematiky struktury grafu scény – kromě jiného si ukážeme, jak se takový graf zakresluje, přičemž použijeme zápis obvyklý v oficiálním tutoriálu.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět