holodepth

Three.js · Sahne grafiği

Object3D ve sahne hiyerarşisi

Three.js'te nesneleri çoğu zaman yalnızca dünya koordinatında “yan yana” koymazsınız; ebeveyn–çocuk bağları kurarsınız. Araba döndüğünde tekerlekler onunla birlikte döner; kapı kolu kapıya bağlı kalır; bağımsız liste yerine bağımlı hareket sistemi. Bu, 2B DOM ağacına benzer bir fikir; 3B’de dönüşüm zinciri matrislerle hesaplanır.

Ortak taban sınıf Object3D'dir: Mesh, Group, Camera, Light ve kök Scene buradan türer; hepsinde position, rotation, scale ve add / remove aynı dille konuşur. Sahne giriş “evrende ne var?” ve arka plan / sis gibi ortamı anlatır; bu sayfa nesnelerin birbirine nasıl bağlandığını ve yerel ile dünya uzayını açar.

Kapsam: local / world, transform ve pivot, getWorldPosition, matrixAutoUpdate, parent–child, THREE.Group, güneş sistemi örneği ve API tablosu. Animasyon döngüsünde hareket ettirdiğiniz şey çoğu zaman bu grafikteki bir Object3D'dir; tick içinde güncelleme, geometri detayı ise Geometri giriş konusundadır.

Hiyerarşi ve koordinat uzayları

Yerel (local) ve dünya (world) koordinatları

Hiyerarşiyi kullanmanın ilk adımı, bir nesnenin konumunun neye göre ifade edildiğini bilmektir.

  • Yerel uzay (local space): position, rotation ve scale değerlerinin okunduğu çerçevedir — nesne ebeveynine (parent) göre nerede ve nasıl durduğunu söyler. Üst öğe yoksa ebeveyn çoğu zaman doğrudan Scene'dir; tekerleği araba grubuna add ettiğinizde tekerleğin yerel konumu “yan tarafta biraz” kalır, araba grubunu hareket ettirdiğinizde dünya konumunu elle yazmanız gerekmez. İç içe gruplarda her seviye kendi yerel değerini tutar; birleşim üstten aşağı çarpılır.
  • Dünya uzayı (world space): Sahne kökenine (genelde (0, 0, 0)) göre birikmiş gerçek konum ve yönelimdir; ebeveyn zincirindeki tüm dönüşümler bu sonuca yansır. Fizik, çarpışma, ışık gölgesi hedefi veya “kameradan kaç birim uzakta?” gibi sorular dünya uzayında sorulur. Okumak için getWorldPosition() kullanılır — ayrıntı dünya konumu ve matris bölümünde; dünya değerini doğrudan yazmak nadiren doğru API’dir, çoğu zaman yerel transform veya attach tercih edilir.

Örnek: Bir araba modelinde tekerlek, arabanın merkezine göre yan tarafta olabilir (yerel). Araba dünyada ilerlediğinde tekerleğin dünya konumu, arabanın dönüşümüyle birlikte güncellenir.

Temel transformlar: position, rotation, scale

Tüm Object3D türevleri üç temel transform özelliği taşır: position, rotation ve scale. Bu değerler yerel uzayda tutulur ve ebeveyn–çocuk hiyerarşisi boyunca birleşerek dünya konumunu ve yönelimini oluşturur.

rotation özelliği Euler açılarıyla tutulur; değerler radyan cinsindendir.

Her Object3D için dönüş ve ölçekleme işlemleri, nesnenin kendi origin (pivot) noktasına göre uygulanır; bu nokta çoğu modelde yerel köken
(0, 0, 0) etrafındadır.

Dünya konumu ve matris güncellemesi

Bir nesnenin dünya koordinatlarındaki konumunu almak için getWorldPosition() kullanılır; sonuç, verdiğiniz vektöre yazılır:

object.getWorldPosition(new THREE.Vector3());

Üretilen vektörü her karede tekrar kullanacaksanız tek bir Vector3 örneğini saklamak daha verimlidir.

Three.js varsayılan olarak her karede transform matrislerini otomatik günceller (matrixAutoUpdate açık). Bu davranış kapatılarak; yalnızca dönüşümü seyrek değişen statik nesnelerde ve bilinçli senaryolarda; gereksiz matris yeniden hesaplaması azaltılabilir; bu ileri düzey bir optimizasyondur ve genelde manuel updateMatrix() ihtiyacı doğurur.

Parent–child ilişkisinin gücü

Bir nesneyi diğerine .add(çocuk) ile eklediğinizde, çocuk ebeveynin transform zincirine girer: konum, dönüş ve ölçek üstten aşağı etkiler.

İki kural, add sonrası davranışı özetler; yerel / dünya ayrımı yukarıda:

  • Miras (üstten aşağı): Ebeveyn dönerse, ötelenirse veya ölçeklenirse çocuk (ve onun alt ağacı) dünya uzayında birlikte taşınır — çocuğun yerel değerleri aynı kalsa bile dünya sonucu değişir. Güneş sistemi örneğinde ay Dünya etrafında dönerken Dünya’nın yörüngesi de taşınır; hepsi zincirle gelir (uygulama). Negatif ölçek gibi uç durumlar ayna etkisi yaratır; çoğu projede ölçeği bilinçli ve pozitif tutun. visible gibi bazı bayraklar da hiyerarşide pratikte üstten etkilenir.
  • Bağımsızlık (aşağıdan yukarı yerel): Çocuğun position / rotation / scale değerlerini değiştirmek yalnızca ebeveyne göre ilişkiyi günceller; ebeveynin dünya konumu veya rotasyonu değişmez. Karakter grubunu hareket ettirirken kola yerel açı vermek bu yüzden güvenlidir — tüm figür taşınmaz, kol eklemi yerelde döner. Ebeveyni değiştirmeden dünya konumunu korumak için tablodaki attach kalıbına bakın; kardeş çocuklar birbirinin yerel transformundan etkilenmez.

THREE.Group: görünmez konteyner

THREE.Group, geometrisi olmayan bir Object3D türevidir; parçaları mantıksal olarak toplamak için kullanılır.

Neden? Örneğin karakterin tüm mesh'lerini (baş, gövde, kollar) tek Group altında toplayıp characterGroup.position.x = 10 ile tüm figürü birlikte taşımak.

Teknik tablo: hiyerarşi metotları

Metot İşlev Kullanım senaryosu
.add(object) Nesneyi çocuk olarak bağlar. Silahı karakterin el bone'una veya gruba bağlamak.
.remove(object) Nesneyi bu düğümün altından çıkarır. Sahneden ayırmak veya başka ebeveyne taşımadan önce söküm.
.attach(object) Nesnenin dünya transformunu koruyarak ebeveyni değiştirir; çocuk başka bir düğümün altına alınırken ekranda zıplamaz. Yer değiştirirken "zıplamayı" önlemek.
.traverse(callback) Sahne grafiğini derinlik öncelikli (depth-first) gezer. Gruptaki tüm mesh'lerde materyal veya gölge bayrağı ayarlamak.

Uygulama: güneş sistemi mantığı

Dünya'nın güneş etrafında, ay'ın dünya etrafında dönmesi; üst grup dönünce alt grupların birlikte hareket etmesi için klasik bir örnektir. sunMesh, earthMesh, moonGeo / moonMat ve sahne kurulumu varsayılmıştır.

const solarSystem = new THREE.Group();
const earthGroup = new THREE.Group();
scene.add(solarSystem);

solarSystem.add(sunMesh);

solarSystem.add(earthGroup);
earthGroup.position.x = 10;
earthGroup.add(earthMesh);

const moonMesh = new THREE.Mesh(moonGeo, moonMat);
moonMesh.position.x = 2;
earthGroup.add(moonMesh);

function animate() {
  requestAnimationFrame(animate);

  solarSystem.rotation.y += 0.01;
  earthGroup.rotation.y += 0.02;

  renderer.render(scene, camera);
}

animate();

Holodepth notu: matrixWorld ve derinlik

Three.js her karede hiyerarşiye göre dünya matrislerini (matrixWorld) günceller; yerel matrisler için matrixAutoUpdate varsayılan olarak açıktır. Çok derin iç içe yapılar (onlarca seviye) bu hesaplamayı artırır; mümkün olduğunca yassı ve amaca uygun bir sahne grafiği kurmak performans için iyidir.