Navigace

Hlavnφ menu

 

Java a 3D grafika - graf scΘny

V p°edchozφm Φlßnku jsme si ukßzali, jak se s pomocφ Java 3D API vytvß°φ jednoduchß scΘna. V tomto Φlßnku se podφvßme podrobn∞ji na problematiku grafu scΘny. Ukß₧eme si, jak jej zakreslovat a seznßmφme se s bßzov²mi t°φdami v∞tÜiny objekt∙ objevujφcφch se ve scΘn∞.

Jak zakreslovat graf scΘny

Jak znßmo, dokß₧e obΦas jeden obrßzek osv∞tlit urΦitou problematiku daleko lΘpe ne₧ n∞kolik desφtek °ßdk∙ textu a v p°φpad∞ grafu scΘny to platφ dvojnßsob. Jen si zkuste p°edstavit, jak slovy popisujete nßsledujφcφ jednoduch² graf:

jednoduch² graf scΘny

A to obsahuje pouze t°i barevnΘ krychle (ColorCube), z nich₧ dv∞ jsou transformovßny jednφm spoleΦn²m objektem TransformGroup, z Φeho₧ jedna je transformovßna jeÜt∞ dalÜφm objektem TransformGroup, a t°etφ je transformovßna jin²mi dv∞ma objekty TransformGroup.

A te∩ popravd∞. ╚emu jste rozum∞li lΘpe? Obrßzku, p°esto₧e jste v n∞m neznali nejmΘn∞ polovinu pou₧it²ch symbol∙, nebo p°edchßzejφcφmu zmatenΘmu textu? A co teprve, kdybyste v obrßzku v²znam vÜech symbol∙ znali? Myslφm si, ₧e obrßzek vyhrßvß.

Nynφ si poj∩me vysv∞tlit v²znam pou₧it²ch symbol∙. Nßsledujφcφ obrßzek je vÜechny shrnuje. (Tento zp∙sob zßpisu je p°evzat z oficißlnφho tutorißlu.)

pou₧φvanΘ symboly

Se t°φdami VirtualUniverse a Locale jsme se seznßmili ji₧ minule. Te∩ je na Φase vysv∞tlit si, k Φemu slou₧φ ty zb²vajφcφ. Instance t°φd odvozen²ch od prvnφ z nich, t°φdy Group, majφ v grafu, °eΦeno slovy klasickΘ terminologie pro popis strom∙, roli uzl∙, tzn. mohou mφt pouze jednoho rodiΦe a neomezen∞ potomk∙.

T°φda Leaf je nadt°φdou pro t°φdy, jejich₧ instance jsou v danΘm stromu listy, co₧ znamenß, ₧e u₧ nemajφ ₧ßdnΘ dalÜφ potomky. P°φkladem m∙₧e b²t t°φda ColorCube, se kterou jsme se seznßmili v minulΘm Φlßnku a se kterou pracujeme i dnes.

Mo₧nß vßs nynφ napadß otßzka, proΦ jsou v ukßzkovΘm grafu objekty ColorCube zobrazeny jako obdΘlnφky a ne jako troj·helnφky, co₧ by podle v²Üe uvedenΘho bylo jist∞ sprßvn∞jÜφ. Inu, tady zase jednou zvφt∞zil pragmatismus nad p°esn²m vyjad°ovßnφm. On toti₧ troj·helnφk nenφ prßv∞ nejvhodn∞jÜφ pro zßpis delÜφho textu. Z toho d∙vodu, pokud nßs bude v budoucnu zajφmat u n∞jakΘho objektu v grafu jeho p°esn² nßzev, zobrazφme jej jako obdΘlnφk.

P°edposlednφ ze symbol∙ v tabulce, ovßl, oznaΦuje instance t°φd, kterΘ jsou odvozeny od t°φdy NodeComponent. Podt°φdami t°φdy NodeComponent jsou nap°φklad t°φdy Appearance a Geometry, se kter²mi se blφ₧e seznßmφme v n∞kterΘm z dalÜφch Φlßnk∙ tΘto sΘrie. Prozatφm snad postaΦφ, kdy₧ si °ekneme, ₧e t°φdy odvozenΘ od tΘto t°φdy nejsou formßln∞ p°φmo souΦßstφ stromu, proto₧e na n∞ odkazujφ objekty list∙ (Leaf), co₧ by jinak nebylo mo₧nΘ (list p°ece nem∙₧e mφt potomky), nejednß se tedy formßln∞ o vztah potomek-rodiΦ.

Äijφcφ a zkompilovanΘ objekty

Vlo₧φme-li objekt BranchGroup do objektu Locale, stanou se tento objekt a objekty v n∞m obsa₧enΘ takzvan∞ ₧iv²mi. To znamenß, ₧e kv∙li v²konu bude graf scΘny p°eveden do v²hodn∞jÜφ podoby, co₧ s sebou nev²hodu v tom, ₧e ji₧ nebudeme moci nadßle p°idßvat objekty do objekt∙ Group nebo m∞nit transformaΦnφ matici v objektech TransformGroup.

Pochopiteln∞ jsou vÜak situace, kdy scΘnu chceme m∞nit i nadßle - a¥ u₧ pot°ebujeme animovat existujφcφ objekty nebo p°idßvat novΘ. Pak musφme n∞jak oznaΦit ty Φßsti scΘny, kterΘ se budou m∞nit. K tomu slou₧φ metody void setCapability(int bit), void clearCapability(int bit) a boolean getCapability(int bit). Parametr bit typu int, p°edßvan² vÜem t∞mto metodßm, nese bitov² p°φznak urΦujφcφ, co je s dan²m objektem (respektive jeho potomky), mo₧nΘ d∞lat. Metoda setCapability(int bit) "zapφnß" tento p°φznak, metoda clearCapability(int bit) tento p°φznak vypφnß a koneΦn∞ metoda getCapability(int bit) vracφ true, pokud je dan² p°φznak nastaven².

Nap°φklad ve t°φd∞ Group jsou definovßny mimo jinΘ nßsledujφcφ p°φznaky: ALLOW_CHILDREN_EXTEND dovolujφcφ p°idßvat dalÜφ objekty do danΘho objektu Group, ALLOW_CHILDREN_READ dovolujφcφ p°istupovat k potomk∙m danΘho objektu a ALLOW_CHILDREN_WRITE umo₧≥ujφcφ upravovat odkazy na potomky tohoto objektu. Ve t°φd∞ TransformGroup jsou pak definovßny dalÜφ p°φznaky: ALLOW_TRANSFORM_READ dovolujφcφ p°istupovat k transformaΦnφ matici a pota₧mo i jejφm jednotliv²m slo₧kßm (rotace, posunutφ) a ALLOW_TRANSFORM_WRITE umo₧≥ujφcφ m∞nit transformaci, co₧ je nezbytnΘ nap°φklad pro animovßnφ. Krom∞ ji₧ zmφn∞n²ch p°φznak∙ vÜak existujφ i dalÜφ, s nimi₧ se setkßme v n∞kterΘm z dalÜφch Φlßnk∙.

Sice je mo₧nΘ renderovat i scΘnu, kterß je pouze ₧ijφcφ, ale pokud chcete v∞tÜφ rychlost, je pot°eba objekty BranchGroup ve scΘn∞ jeÜt∞ navφc "zkompilovat". K tomu slou₧φ metoda compile(), jejφ₧ volßnφ zp∙sobφ dalÜφ zm∞ny v internφ reprezentaci scΘny. Jejφ pou₧φvßnφ je nav²sost u₧iteΦnΘ a neexistuje prakticky ₧ßdn² d∙vod, proΦ ji ignorovat.

Mal² p°φklad

Nynφ si na krßtkΘm p°φkladu ukß₧eme pou₧itφ toho, co jsme se dnes nauΦili. V²sledek nebude nijak osl≥ujφcφ, p∙jde o dalÜφ variaci na tΘma barevnΘ krychle. Nejprve vytvo°φme scΘnu s barevnou krychlφ, jejφm₧ rodiΦem bude objekt TransformGroup, pak ji zkompilujeme a teprve a₧ potom ji budeme transformovat ·pravou objektu TransformGroup, co₧ znamenß, ₧e se nevyhneme pou₧itφ metody setCapability(int bit), co₧ je v podstat∞ hlavnφm ·Φelem tohoto p°φkladu. Celou scΘnu si pro procviΦenφ rovn∞₧ zakreslφme.

graf scΘny p°φkladu

Zde nßsleduje zdrojov² k≤d p°φkladu:

package interval.j3d;

import java.awt.*;
import javax.swing.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;
import javax.media.j3d.*;
import javax.vecmath.*;

public class Capabilities extends JFrame{
   TransformGroup tg;
   public Capabilities() {
      super("Ukßzka pou₧itφ setCapability()");
      //Na nßsledujφcφch °ßdcφch vytvo°φme Canvas3D
      Container pane = getContentPane();
      pane.setLayout(new BorderLayout());
      GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
      Canvas3D canvas = new Canvas3D(config, false);
      pane.add("Center", canvas);
      //vytvo°φme objekt SimpleUniverse
      SimpleUniverse universe = new SimpleUniverse(canvas);
      //nastavφme vzdßlenost pozorovatele od monitoru na 2m
       universe.getViewingPlatform().setNominalViewingTransform();
      //p°idßme BranchGroup vytvo°en² v metod∞ vytvorBranchGroup()
      //do objektu SimpleUniverse
      universe.addBranchGraph(vytvorBranchGroup());
      //upravφme transformaci v objektu TransformGroup tg,
      //kter² je ji₧ souΦßstφ grafu scΘny, co₧ by nebylo mo₧nΘ,
      //kdybychom v metod∞ vytvorBranchGroup nevolali
      //metodu setCapability s parametrem ALLOW_TRANSFORM_GROUP
      tg.setTransform(vytvorTransform());
      addWindowListener(new java.awt.event.WindowAdapter() {
       public void windowClosing(java.awt.event.WindowEvent evt) {
        System.exit(0);
        }
      });
   }
   protected BranchGroup vytvorBranchGroup(){
      //ko°en tΘto Φßsti scΘny
      BranchGroup bg = new BranchGroup();
      //tento objekt upravujeme a₧ dßle v konstruktoru
      tg = new TransformGroup();
      //nastavφme, ₧e chceme nadßle m∞nit transformaΦnφ matici
      //tohoto objektu
      tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
      //p°idßme objekt TransformGroup tg jako potomka
      //do objektu bg
      bg.addChild(tg);
      //vlo₧φme jeÜt∞ barevnou krychli jako potomka zmφn∞nΘho
      //objektu TransformGroup tg
      tg.addChild(new ColorCube(0.3));
      //zkompilujeme scΘnu
      bg.compile();
      return bg;
   }
   protected Transform3D vytvorTransform(){
      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);
      return tr2;
   }
   public static void main(String[] args){
      new Capabilities().show();
   }
}

Na tomto p°φkladu sice nenφ u₧iteΦnost popsan²ch technik p°φliÜ z°etelnß, a₧ se ale budeme zab²vat animovßnφm objekt∙, neobejdeme se bez nich. Nßsledujφcφ obrßzek je v²sledkem pou₧itφ p°edchßzejφcφho k≤du:

v²sledek p°φkladu

P°φÜt∞ se seznßmφme s t°φdami pro tvorbu geometrick²ch primitiv a ukß₧eme si, jak upravovat jejich vzhled (barvu a dalÜφ vlastnosti) pomocφ objekt∙ Appearance.

P°edchozφ Φlßnky

Ku₧elka, Ond°ej (19.11. 2003)