Navigace

Hlavnφ menu

 

Java a 3D grafika - Geometry (PointArray, LineArray a TriangleArray)

V tomto Φlßnku se zaΦneme zab²vat vytvß°enφm objekt∙ prost°ednictvφm instancφ t°φdy Shape3D. Ukß₧eme si, jak pomocφ ·seΦek vytvo°it drßtov² model krychle, a pak si povφme, jak se dajφ pomocφ troj·helnφk∙ vytvß°et t∞lesa se st∞nami.

Ne₧ se pustφte do Φtenφ tohoto Φlßnku, doporuΦuji vßm o₧ivit si pov∞domφ o tom, jakΘ objekty se objevujφ v grafu scΘny, jakΘ podmφnky musφ graf scΘny spl≥ovat a k Φemu jsou dobrΘ objekty Appearance, prost°ednictvφm Φlßnku Java a 3D grafika - graf scΘny.

Pro vytvß°enφ trojrozm∞rn²ch objekt∙ se pou₧φvajφ objekty Shape3D, kterΘ mohou odkazovat na instance podt°φd abstraktnφ t°φdy Geometry a na objekty Appearance. (Jeden objekt Shape3D m∙₧e odkazovat i na n∞kolik objekt∙ Geometry, ale ty musφ b²t stejnΘho typu.) Tyto objekty se jim p°i°azujφ bu∩ p°φmo v konstruktoru Shape3D(Geometry geometry, Appearance appearance), nebo pomocφ metod setGeometry(Geometry geometry) a setAppearance(Appearance appearance).

Objekty Geometry obsahujφ vlastnφ data objekt∙, tedy sou°adnice vrchol∙, normßlovΘ vektory, barvy vrchol∙ a sou°adnice slou₧φcφ k otexturovßnφ. V objektech Appearance pak jsou ulo₧eny informace o materißlu, Üφ°ce Φar, tlouÜ¥ce bod∙, o tom, zda se mß nebo nemß pou₧φt antialiasing a tak dßle. Podrobn∞ji jsme se ale t°φd∞ Appearance v∞novali v Φlßnku o grafick²ch primitivech, tak₧e na tomto mφst∞ snad postaΦφ jen tato krßtkß zmφnka.

T°φda GeometryArray a jejφ potomci

Vzhledem k tomu, ₧e t°φd odvozen²ch od t°φdy Geometry je pom∞rn∞ dost, rozlo₧φme si povφdßnφ o nich do n∞kolika Φlßnk∙. V tomto Φlßnku zaΦneme n∞kolika potomky t°φdy GeometryArray, konkrΘtn∞ t°φdami PointArray, LineArray a TriangleArray.

JednoduÜÜφ verze konstruktor∙ vÜech Φty° zmφn∞n²ch t°φd p°ebφrajφ pouze dva parametry - poΦet vrchol∙ a jejich "formßt", tedy bitovΘ p°φznaky °φkajφcφ, co p°esn∞ bude v danΘm objektu Geometry ulo₧eno. P°φznaky definovanΘ ve t°φd∞ GeometryArray jsou COORDINATES pro sou°adnice, NORMALS pro normßlovΘ vektory, COLOR_3 pro barvu bez alfa-transparence, COLOR_4 pro barvu s alfa-transparencφ, TEXTURE_COORDINATES_2, TEXTURE_COORDINATES_3 a TEXTURE_COORDINATES_4 pro sou°adnice textur. Tak nap°φklad budeme-li chtφt vytvo°it instanci t°φdy PointArray obsahujφcφ Φty°i barevnΘ body, bude volßnφ konstruktoru vypadat takto: PointArray(4, GeometryArray.COORDINATES | GeometryArray.COLOR_3);.

Mßme-li u₧ objekt GeometryArray vytvo°en², musφme do n∞ho vlo₧it pot°ebnß data. Nßsledujφ metody slou₧φcφ pro nastavenφ sou°adnic vrchol∙:

  • public void setCoordinates(int index, float[] coordinates)
  • public void setCoordinates(int index, double[] coordinates)
  • public void setCoordinates(int index, Point3f[] coordinates)
  • public void setCoordinates(int index, Point3d[] coordinates)

V poli "coordinates" jsou ulo₧eny sou°adnice vrchol∙. Parametr "index" oznaΦuje pozici v poli "coordinates", kde se sou°adnice nachßzejφ. Metody pro nastavenφ barev, normßlov²ch vektor∙ a sou°adnic textur jsou velice podobnΘ a postupn∞ se k nim dostaneme alespo≥ v p°φkladech.

T°φda LineArray

Nynφ u₧ toho vφme dost na to, abychom mohli s vyu₧itφm t°φdy LineArray, kterß je urΦena k vytvß°enφ t∞les z ·seΦek, vytvo°it jednoduchou t°φdu odvozenou od t°φdy Shape3D slou₧φcφ k vytvß°enφ drßtov²ch krychlφ. Jejφ k≤d nßsleduje:

package interval.j3d;

import javax.media.j3d.*;

public class DratovaKrychle extends Shape3D {

 float souradnice[] =
//sou°adnice bod∙, v₧dy dva body pro ·seΦku
   {-1,-1,1, -1,1,1, -1,1,1, 1,1,1,
   1,1,1, 1,-1,1, 1,-1,1, -1,-1,1,
   -1,-1,-1, -1,1,-1, -1,1,-1, 1,1,-1,
   1,1,-1, 1,-1,-1, 1,-1,-1, -1,-1,-1,
   -1,-1,1, -1,-1,-1, -1,1,1, -1,1,-1,
   1,1,1, 1,1,-1, 1,-1,1, 1,-1,-1};

 public DratovaKrychle(float hrana) {
//nastavφme velikost hran
  for (int i = 0; i < 72; i++)
   souradnice[i] *= hrana/2f;
  setGeometry(vytvorGeometry());
  setAppearance(vytvorAppearance());
 }
 Geometry vytvorGeometry(){
//vytvo°φme instanci t°φdy LineArray
  LineArray lineArray = new LineArray(24, GeometryArray.COORDINATES);
//nastavφme sou°adnice
  lineArray.setCoordinates(0, souradnice);
  return lineArray;
 }
 Appearance vytvorAppearance(){
  Appearance app = new Appearance();
//nastavφme tlouÜ¥ku Φßry na 3 pixely, povolφme antialiasing
  LineAttributes la = new LineAttributes(3, LineAttributes.PATTERN_SOLID, true);
  app.setLineAttributes(la);
  return app;
 }
}

Jak m∙₧ete sami vid∞t, je k≤d tΘto t°φdy velice jednoduch². Pouze v konstruktoru vytvß°φ objekt Geometry, do kterΘho vlo₧φ sou°adnice zadanΘ v poli "souradnice", kterΘ jeÜt∞ p°edtφm vynßsobφ parametrem "hrana/2", abychom mohli vytvß°et krychle r∙zn²ch velikostφ. Toto je v²sledek:

Jednoduchß drßtovß krychle

Pou₧itφ tΘto t°φdy a takΘ dalÜφch t°φd v tomto Φlßnku, krom∞ t°φdy PointArray, je mnohdy dost ne·spornΘ z hlediska nßrok∙ na pam∞¥ û nap°φklad sou°adnice ka₧dΘho z vrchol∙ krychle v p°φkladu uklßdßme t°ikrßt. ╪eÜenφm mohou b²t podt°φdy, bu∩ t°φdy GeometryStripArray nebo t°φdy IndexedGeometryArray. O tom ale a₧ jindy.

T°φda PointArray

T°φda PointArray nßm umo₧≥uje zobrazovat jednotlivΘ vrcholy. Ve spojenφ s nφ se hodφ vyu₧φt mo₧nosti nastavenφ tlouÜ¥ky bod∙ prost°ednictvφm t°φdy PointAttributes, jejφ₧ instance se p°ipojujφ k p°φsluÜn²m objekt∙m Appearance. Konstruktor PointAttributes(float pointSize, boolean antialiasing) p°ebφrß dva parametry. Parametr "pointSize" urΦuje tlouÜ¥ku bod∙ a parametr "antialiasing" urΦuje, jestli se mß pou₧φt antialiasing.

T°φdu PointArray vyu₧ijeme k vylepÜenφ p°edchozφho p°φkladu tφm, ₧e do ka₧dΘho vrcholu krychle nakreslφme bod zadanΘ tlouÜ¥ky. NaÜe novß t°φda vÜak nebude rozÜi°ovat t°φdu Shape3D, ale bude odvozena od t°φdy Group (kv∙li nemo₧nosti vklßdat do objekt∙ Shape3D objekty Geometry r∙znΘho typu, v tomto p°φpad∞ tedy instance t°φd LineArray a PointArray).

package interval.j3d;

import javax.media.j3d.*;

public class DratovaKrychle2 extends Group {

 float souradnice[] =
   {1,1,1, -1,1,1, 1,-1,1, 1,1,-1,
   -1,-1,1, -1,1,-1, 1,-1,-1, -1,-1,-1};

 public DratovaKrychle2(float hrana) {
  for (int i = 0; i < 24; i++)
   souradnice[i] *= hrana/2f;
  Shape3D shape2 = new Shape3D();
//objektu shape2 nastavφme objekt Geometry
  shape2.setGeometry(vytvorGeometryBodu());
//objektu shape2 nastavφme objekt Appearance
  shape2.setAppearance(vytvorAppearanceBodu());
//p°idßme objekt DratovaKrychle
  addChild(new DratovaKrychle(hrana));
  addChild(shape2);
 }
 Geometry vytvorGeometryBodu(){
  PointArray pointArray = new PointArray(8, GeometryArray.COORDINATES);
  pointArray.setCoordinates(0, souradnice);
  return pointArray;
  }
 Appearance vytvorAppearanceBodu(){
  Appearance app = new Appearance();
  PointAttributes pa = new PointAttributes(10, true);
  app.setPointAttributes(pa);
  return app;
 }
}

A takto vypadß v²sledek:

Drßtovß krychle se zv²razn∞n²mi vrcholy

Pro lepÜφ p°edstavu si jeÜt∞ ukß₧eme, jak by mohla vypadat instance tΘto t°φdy zakreslenß v grafu scΘny, jak to m∙₧ete vid∞t na nßsledujφcφm obrßzku:

Drßtovß krychle - graf scΘny

T°φda TriangleArray

T°φda TriangleArray slou₧φ, jak u₧ jejφ nßzev napovφdß, k vytvß°enφ t∞les z troj·helnφk∙. Jejφ vyu₧itφ si ukß₧eme na vytvo°enφ Φty°st∞nu. Abychom si takΘ ukßzali, jak pracovat s barvami p°i°azen²mi jednotliv²m vrchol∙m, o₧ivφme st∞ny naÜeho Φty°st∞nu nßhodn∞ vybran²mi barvami.

package interval.j3d;

import javax.media.j3d.*;
import javax.vecmath.*;
import java.util.Random;

public class Ctyrsten extends Shape3D {
//vypoΦφtßme si dv∞ odmocniny, kterΘ budeme pot°ebovat
 float s6 = (float)Math.sqrt(6);
 float s3 = (float)Math.sqrt(3);
//ka₧dß °ßdka odpovφdß jednomu troj·helnφku
 float souradnice[] = {
  -0.5f,0,-s3/6f, 0,0,s3/3f, 0.5f,0,-s3/6f,
  -0.5f,0,-s3/6f, 0,s6/3f,0, 0,0,s3/3f,
  0,0,s3/3f, 0,s6/3f,0, 0.5f,0,-s3/6f,
  0.5f,0,-s3/6f, 0,s6/3f,0, -0.5f,0,-s3/6f};
 public Ctyrsten(float hrana) {
  for (int i = 0; i < 36; i++)
   souradnice[i] *= hrana;
  setGeometry(vytvorGeometry());
 }
 Geometry vytvorGeometry(){
  TriangleArray ta = new TriangleArray(12, GeometryArray.COORDINATES | GeometryArray.COLOR_3);
  ta.setCoordinates(0,souradnice);
//obarvφme st∞ny nßhodn∞ vybran²mi barvami
  Random rand = new Random();
  for (int i = 0; i < 4; i++){
   Color3f color = new Color3f(rand.nextFloat(), rand.nextFloat(), rand.nextFloat());
   for (int j = 0; j < 3; j++)
    ta.setColor(3*i+j, color);
   }
  return ta;
 }
}

Obarvenφ tohoto t∞lesa provßdφme v metod∞ vytvorGeometry(), kde volßnφm metody setColor(int i, Color3f color) nastavujeme ka₧d²m t°em bod∙m urΦujφcφm st∞nu jednu nßhodn∞ vybranou barvu. Barvy jsme ale klidn∞ mohli nastavit odliÜnΘ pro ka₧d² vrchol - pak by se v jednotliv²ch st∞nßch postupn∞ m∞nily.

╚ty°st∞n

Objekty, kterΘ jsme v tomto Φlßnku vytvo°ili, majφ jeden velk² nedostatek - sv∞tla na n∞ nemajφ ₧ßdn² ·Φinek. Jak se s tφmto nedostatkem vypo°ßdat, o tom si povφme p°φÜt∞.

Ku₧elka, Ond°ej (7. 5. 2004)