Java Temelleri : Java 3D

advertisement
Java 3D
Java 3D
Son yıllarda çoklu ortamda ilerleme kaydeden Java, Java3D ile yüksek
performans isteyen üç boyutlu grafiklerde de 'Ben varım!' diyor.
OpenGL (Open Graphics Library) üç boyutlu (3D) uygulamalara yazmak için dilden ve platformadan bağımsız standart bir spesifikasyondur. Üç
boyutlu, hatta iki boyutlu karmaşık şekiller çizmeye yaramaktadır. Oyunların çoğu OpenGL tabanlıdır. DirectX, OpenGL'e alternatif olarak
Microsoft tarafından geliştirilmiş üç boyutlu grafik ve çoklu ortam kütüphanesidir.
Java3D ise OpenGL veya DirectX altyapısını kullanarak üç boyutlu nesnelerle program yapmaya yarayan bir Java küyüphanesidir. OpenGL ve
DirectX düşük düzeyli yani makineye daha yakın temel fonksiyonları içerirken, Java3D nesneye yönelik programlamaya uygun bir yazılım
altyapısıdır.
Java 3D Kütüphaneleri
Java 3D kütüphanesi java.media.j3d paketindir. Üç boyutlu nesnelerde çok miktarda vektor ve matris işlemleri olduğu için javax.vecmath
kütüphanesi de Java3D kütüphanelerine dahildir. Java 3D kütüphanesi çok temel sınıflar içerir, basit bir örnek için bir çok miktarda kod yazmak
gerekir. O yüzden Sun firması com.sun.j3d ile başlayan çok miktarda yardımcı ve faydalı nesne geliştirmiştir. Örneğin Java 3D'de küp yapmaya
yarayan bir nesne yokdur, bunun için com.sun.j3d.utils.geometry.ColorCube adında, her yüzeyinde değişik bir renk olan bir küp bulunmaktadır.
Elbette progragmcı bunu kendi de yapabilir ama Sun'ın yardımcı sınıflar basit bir üç boyutlu nesne yapmak için en başta bir miktar kod yazmak
zorunda olmaktan kurtarmaktadır.
Canvas3D
Üç boyutlu nesnelerin çizilmesi için bir tuval yani 'canvas' gereklidir. Java 3D kütüphanesi Java'nın standart arayüz kütüphanesi AWT üzerinde
çalışır. Canvas3D sınıfı java.awt.Canvas sınıfını genişletir. Örneğin
public class ColorCubeTest extends Frame {
public ColorCubeTest() {
setLayout(new BorderLayout());
GraphicsConfiguration config =SimpleUniverse.getPreferredConfiguration();
Canvas3D canvas = new Canvas3D(config);
add(BorderLayout.CENTER,canvas);
}
}
şeklindeki kod, sistemin grafik konfigurasyonunu kullanan bir tuval oluşturmakta ve bir pencerenin ortasına yerleştirmektedir.
Universe (Evren)
Java3D'de çizilen bütün nesneler bir evren'de ('universe'de) yer alır. Öncelikle tuval (canvas) üzerinde çalışan evren oluşturulur. Evren aslında
VirtualUniverse sınıfıyla temsil edilir ancak Sun'ın faydalı sınıfları arasında bu sınıfı genişleten SimpleUniverse sınıfı bulunmaktadır. Örneğin
public class ColorCubeTest extends Frame {
public ColorCubeTest() {
// ...
SimpleUniverse universe = createUniverse(canvas);
BranchGroup group =createGroup();
universe.addBranchGraph(group);
}
private SimpleUniverse createUniverse(Canvas3D canvas) {
SimpleUniverse universe = new SimpleUniverse(canvas);
ViewingPlatform platform=universe.getViewingPlatform();
platform.setNominalViewingTransform();
return universe;
}
biçiminde kod bir evren oluşturmakta ve tuvale atamaktadır.
Point (Nokta) & Vector (Vektör)
Uzayda bir noktayı göstermek için PointXXX sınıfları bulunmaktadır. Bunlar 2 ve 3 boyutlu ve 4 boyutlu (x,y,z üç boyutu ve
homojen kordinatlardaki dördüncü 'w' boyutu) gibi boyut seçeneklerine, integer,float ve double tip seçeneklerine göre çeşitli nokta
sınıfları bulunmaktadır. Örneğin Point3d
Behaviour (Davranış)
www.dersmax.net
Java 3D
1
Java 3D
Normal şartlarda canvas ve evren durağandır. İzleyici gördüğü üç boyutlu nesneler karşısında hareket edemez. Bir kamera hareketi
gibi bir işlev görmek için ViewPlatformBehavior sınıfı bulunmaktadır. Behaviour (davranış) sınıfları kullanıcı ile üç boyutlu evren
arasında iletişimi sağlar. ViewPlatformBehavior ise, farenin sol tuşuyla şeklin etrafında dönülen, sağ tuşuyla da şeklin karşısında
harekete edilen eylemleri destekler. Bir evrene bir 'davranış' eklemek için
public class ColorCubeTest extends Frame {
// ...
private SimpleUniverse createUniverse(Canvas3D canvas) {
SimpleUniverse universe = new SimpleUniverse(canvas);
ViewingPlatform platform=universe.getViewingPlatform();
platform.setNominalViewingTransform();
ViewPlatformBehavior behavior=createBehaviour(canvas);
platform.setViewPlatformBehavior(behavior);
return universe;
}
private ViewPlatformBehavior createBehaviour(Canvas3D canvas){
int flags=OrbitBehavior.REVERSE_ALL |OrbitBehavior.STOP_ZOOM;
OrbitBehavior behavior = new OrbitBehavior(canvas,flags);
Point3d origin = new Point3d(0.0,0.0,0.0);
BoundingSphere bounds =new BoundingSphere(origin, 100.0);
behavior.setSchedulingBounds(bounds);
return behavior;
}
}
Burada orijin etrafında dönme yapılabilen kullanıcı etkileşimi kodlanmıştır.
BranchGroup (Dal Grubu)
Java3D'de her nesne bir 'dal grubu' (BranchGroup) içerisindedir. Yani bir veya daha fazla nesne belli bir orijine göre belli bir
koordinat sistemini taban alarak konumlandırılmıştır ve bu nesnelerden oluşan 'dal grubu' birlikte hareket eder. Bir üç boyutlu
nesne oluşturulduktan sonra bir dal grubu oluşturulur ve nesne o dal grubuna eklenir. O dal grubu da evrene eklenir. Evren > Dal
Grubu > Şekil şeklinde bir yapı vardır. Evrende dal grupları, dal gruplarında da şekiller bulunur. Bir dal grubu ötelenir veya
döndürülürse o dal grubundakiğ bütün şekiller ötelenir veya döndürülür. Şekillere örnek olarak ColorCube adında, her yüzeyi
değişik renkte olan bir nesne alınabilir. Bu şekli bir dal grubuna eklemek ve bu dal grubuna da bir evrene eklemek için
public class ColorCubeTest extends Frame {
public ColorCubeTest() {
// ...
BranchGroup group =createGroup();
universe.addBranchGraph(group);
}
private BranchGroup createGroup(){
BranchGroup group = new BranchGroup();
group.addChild(new ColorCube(0.3));
return group;
}
}
şeklinde bir kod yazılır. Farenin sürükle bırak özelliğiyle etrafında gezinebildiğimiz bir ColorCube'ü içeren bir evren için tam bir
örnek şu şekilde yazılabilir:
Godoro.Web.Common/Upload/HTMLEditorFolder/ColorCubeTest.java
www.dersmax.net
Java 3D
2
Java 3D
Light (Işık)
Java3D'de üç boyutlu ortamda ışık kullanılabilir. Işık, PointLight yani noktasal (bir noktadan her yöne doğru yayılan),
DirectionalLight yani doğrusal (bir noktadan belli bir yöne doğru yayılan) ve AmbientLight yani ortamsal (belli bir merkezi ve
yönü olmadan ortamda bulunan) biçimlerde olabilir. Ayrıca bir ışığın sınırları belirlenebilir, ışık o sınırlar dışına ulaşmaz. Işık
nesneleri dal grubu (BranchGroup) nesnelerine bir şekil gibi eklenirler ve grubun bir parçası olurlar. Doğrusal ışık eklemek için
private BranchGroup createGroup(){
BranchGroup group = new BranchGroup();
// ...
Light directional=createDirectionalLight();
group.addChild(directional);
return group;
}
private Light createDirectionalLight(){
Color3f color = new Color3f(1f, 1f, 1f);
Point3d origin = new Point3d(0.0,0.0,0.0);
BoundingSphere bounds = new BoundingSphere(origin, 100.0);
Vector3f direction = new Vector3f(4.0f, -7.0f, -12.0f);
DirectionalLight light = new DirectionalLight(color, direction);
light.setInfluencingBounds(bounds);
return light;
}
şeklinde bir kod yazılabilir. Burada bir ışığın rengi, yönü ve sınırları verilmektedir. Ortam ışığı için oluşturmak için de
private Light createAmbientLight(){
Color3f color = new Color3f(.5f,.5f,.5f);
AmbientLight light = new AmbientLight(color);
Point3d origin = new Point3d(0.0,0.0,0.0);
BoundingSphere bounds = new BoundingSphere(origin, 100.0);
light.setInfluencingBounds(bounds);
return light;
}
şeklinde bir kod yazılır.
Belli bir yönden kırmızı ışık alan bir küre örneği şu şekilde yapılabilir
Godoro.Web.Common/Upload/HTMLEditorFolder/LightSphereTest.java
Appearance (Görünüm), Material (Malzeme) & Texture (Doku)
Üç boyutlu nesnelerin fiziksel boyutları dışında Appearance sınıfıya belirtilen "görünümleri" olur. Görünümün en önemli bileşenleri
Material sınıfıyla belirtilen malzeme, Texture sınıfıyla belirtilen doku özellikleridir. Material sınıfı maddenin rengini ve yaydığı ışığı
tanımlar. Texture ise bir resim olabildiği gibi belli bir formüle göre görünüşü belirleyen bir yapı da içerebilir. Bir malzeme şu şekilde
yüklenebilir :
private Material createMaterial() {
Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
Color3f red = new Color3f(0.7f, .15f, .15f);
Material material= new Material(white, red, white, red, 1.0f);
return material;
}
www.dersmax.net
Java 3D
3
Java 3D
Burada malzemeye 'ambient', 'emissive', 'diffuse' gibi malzemesel renk özellikleri ve palaklık tanımı yapılmaktadır.
Doku yüklemek için
private Texture createTexture(){
String file="EPicsOnderTekerTied.jpg";
TextureLoader loader=new TextureLoader(file,"LUMINANCE",new Container());
Texture texture = loader.getTexture();
texture.setBoundaryModeS(Texture.WRAP);
texture.setBoundaryModeT(Texture.WRAP);
Color4f color= new Color4f( 0.0f, 1.0f, 0.0f, 0.0f );
texture.setBoundaryColor( color);
return texture;
}
şeklinde bir kod yazılabilir. Burda bir resim dokuya yüklenmekte ve reknk gibi parametreler ayarlanmaktadır. BoundaryMode
olarak S ve T, dokunun kendi düzleminde üzerinde yatay ve dikey yönde resmin dokunun eksik kısımlarını nasıl tamamlayacağı
belirtiliyor. WRAP değeri, resmi yüzey boyunca tekrar tekrar koyulması anlamına gelir.
Bir küre üzerine bir vesikalık fotoğrafı koyan bir örnek şu şekilde yapılabilir :
Godoro.Web.Common/Upload/HTMLEditorFolder/TextureTest.java
Transformation (Dönüşüm)
Bir veya daha fazla şeklin belli bir konum değişikliği yapması 'dönüşüm' (transform) işlemidir. Bir dönüşüm birden fazla dönüşümü,
örneğin bir kaç ötemele (translate) ve dönme (rotate) işlemini içerebilir. Üç boyutta ödeleme veya dönme gibi dönüşüm işlemleri
Transform3D sınıfıyla gösterilir. Bir veya daha fazla dönüşüm işlemini birleştirmek için TransformGroup sınıfı kullanılır. Dönüşüm
uygulanacak şekiller transform grubuna eklenir. Yani bir şekle çeşitli dönüşümlerin uygulanması çeşitli dönüşümler içeren bir
dönüşüm grubuna bir şeklin eklenmesiyle olur. Bir dönüşüm grubuna birden fazla şekil eklenerek çok sayıda şeklin aynı
dönüşümlere tabi olması sağlanabilir.
Basit bir ötemele dönüşümü
private TransformGroup createTransform(float x,float y,float z){
TransformGroup group = new TransformGroup();
Transform3D transform = new Transform3D();
Vector3f vector = new Vector3f(x, y, z);
transform.setTranslation(vector);
group.setTransform(transform);
return group;
}
şeklinde yapılabilir. Burda verilen x, y ve z koordinatları kadar öteleme yapan bir dönüşüm grubu oluşturlmaktadır. Bir dal
grubuna bir şekli dönüştürüp eklemek için
BranchGroup group = new BranchGroup();
Sphere sphere = new Sphere(0.05f);
TransformGroup transform=createTransform(3.0f,4.0f,5.0f);
transform.addChild(sphere);
group.addChild(transform);
www.dersmax.net
Java 3D
4
Java 3D
şeklinde bir kod yazılır. Burda bir küreye (3,4,5) miktarında dönüşüm uygulanır. Sonra dönüşüm grubu dal grubuna eklenir.
Dönüşüm grubu aslında dal grubunun koordinat sistemine göre belli bir dönüşüm uygulanmış yeni bir koordinat sistemidir. Her
dönüşüm, eklendiği grubun koordinat sistemine göre tanımlıdır.
Üç boyutlu uzayda üç boyutun eksenleri boyunca küre (Sphere), koni (Cone) ve kutu (Box) şekillerini dizmek için
private BranchGroup createGroup(){
BranchGroup group = new BranchGroup();
for (float x = -1.0f; x <= 1.0f; x = x + 0.1f){
Sphere sphere = new Sphere(0.05f);
TransformGroup transform=createTransform(x,.0f,.0f);
transform.addChild(sphere);
group.addChild(transform);
}
for (float y = -1.0f; y <= 1.0f; y = y + 0.1f){
Cone cone = new Cone(0.05f, 0.1f);
TransformGroup transform=createTransform(.0f, y, .0f);
transform.addChild(cone);
group.addChild(transform);
}
for (float z = -1.0f; z <= 1.0f; z = z+ 0.1f){
Box box = new Box(0.03f,0.03f,0.03f,null);
TransformGroup transform=createTransform(.0f, .0f, z);
transform.addChild(box);
group.addChild(transform);
}
return group;
}
Burada Sphere, Cone ve Box nesneleri oluşturuluyor, belli bir öteleme yapacak şekilde oluşturulmuş dönüşüm grubuna ekleniyor.
Oluşturulan dönüşüm grupları da asıl dal grubuna ekleniyor. Bu örneğin ışıklandırması da eklenmiş tam hali şu şekilde yazılabilir :
Godoro.Web.Common/Upload/HTMLEditorFolder/TransformTest.java
Animation (Canlandırma) & Interaction (Etkileşim)
Üç boyutlu şekillerle canlandırma (animasyon) yapmak mümkündür. Animsayon için Java3D'ye özel bir kod yazmak gerekmez, belli bir
zamanda şekilleri veya konumlarını değiştirmek yeterlidir. Hareket içeren animasyonlar, bir dal grubuna belli bir dönüşüm uygulamaktan ibarettir.
Örnek olarak bir aşağı bir yukarı giden bir küre yapılabilir. Bunun için belli bir zamanda yapacağı hareketi tanımlayan bir yöntem yazmak gerekir :
public void move() {
height += .1 * sign;
if (Math.abs(height *2) >= 1 ){
sign = -1.0f * sign;
}
Vector3d vector=new Vector3d(1.0, .8, 1.0);
if (height<-0.4f) {
www.dersmax.net
Java 3D
5
Java 3D
vector=new Vector3d(1.0, .8, 1.0);
}else {
vector=new Vector3d(1.0, 1.0, 1.0);
}
transform.setScale(vector);
Vector3f translation=new Vector3f(x,height,0.0f);
transform.setTranslation(translation);
group.setTransform(transform);
}
Burada 'group' adındaki dal grubuna bir dönüşüm uygulanmaktadır. Dönüşüm için yükseklik ('height') sürekli değiştirlmektedir.
Değişimin yönü 'sign' parametresiyle belirlenmekte, belli bir sınıra ulaştığında sign değişkeni tesr işaret almakta ve kürenin hareket
yön ters yönde değişmektedir.
Hareket ettiren yöntemin bir canlandırma oluşturması için bu yöntemin zaman içine tekrar tekrar çağrılmasını bir akış (thread)
veya zamanlayıcı (timer) aracaılığıyla sağlamak gerekir. Bunun için javax.swing.Timer sınıfı kullanılabilir :
ActionListener listener=new ActionListener(){
public void actionPerformed(ActionEvent e ) {
move();
}
};
timer = new Timer(100,listener);
Burada yapılan 100 milisaniye arayla hareket ettiren yöntemin çağrılmasını sağlamaktır.
Canlandırma şekilleri zamana bağlı olarak konum veya şekil değişikliği demektir. Ancak oyun gibi konularda değişimi zamanın
yerine kullanıcının belirlemesi, yani etkileşim (interaction) gerekebilir. Başka bir deyişle kullanıcı fare veya klavye hareketiyle
şekillerin konumu veya biçimi üzerinde değişiklik yapabilir. Örnek olarak aşağı yukarı hareket eden kürenin kullanıcı tarafından
sağa ve sola doğru hareket etmesi sağlanabilir. Bunun için klavyeyi KeyListener olarak dinlemek yeterlidir. Tuşa basıldığında
public void keyPressed(KeyEvent e) {
if (e.getKeyCode()==KeyEvent.VK_RIGHT) {
x+=.1f;
}else if (e.getKeyCode()==KeyEvent.VK_LEFT){
x-=.1f;
}
}
şeklinde sola veya sağa tuşuna basılmasına göre x koordinatı değiştirilir. Zamanlayıcının bir sonraki zaman diliminde hareket
ettiren move() yöntemini çağrılmasıyla şekil yeni konumunda dönüşüm uygulanarak gösterilecektir.
Hem canlandırma hem de kullanıcı etkileşimi içeren örnek şu şekilde yazılabilir :
Godoro.Web.Common/Upload/HTMLEditorFolder/AnimationTest.java
www.dersmax.net
Java 3D
6
Java 3D
Sonuç
Java 3D ile yapılabilecekler yukarıda anlatılanlardan ibaret değil. 3D grafiklerinde olan standart tüm işlemler, şekil değişikliği
(Morphing), üç boyutlu ses (Audio 3D), başka üç boyutlu çizim formatlarını tanıma (örneğin Lightwave )gibi özellikler Java3D'de
bulunmaktadır. Tam anlamıyla bitmiş bir kütüphane gözüyle bakmak zor ama şimdiye kadar yapılanlara bakılarak Java 3D'nin
gelecek vadettiği söylenebilir. Java3D'nin OpenGL/DirectX'le doğrudan çalışan kütüphanelere göre nesneye yönelik ve daha kolay
olduğu söylenebilir. Yakın bir gelecekte 3 boyutlu Java programlamayı oyun ve veri görselleştirme alanlarında sıkça görebiliriz.
Kaynak www.godoro.com/Portal/Content/Article/ArticleViewPage.aspx
www.dersmax.net
Java 3D
7
Download