Three.js · Transform · Koordinat uzayları
İki farklı gerçeklik: Yerel ve dünya uzayı
3D bir sahnede her objenin iki farklı kimlik kartı vardır: biri ebeveyne göre yerel (local) dönüşümü, diğeri sahnenin köküne göre dünya (world) dönüşümü. Bu ayrımı anlamak, objeleri doğru konumlandırmanın ve tutarlı animasyonlar kurmanın anahtarıdır.
Bu sayfa sözlük ve zihinsel model katmanıdır: sahnede gördüğünüz sayıların hangi koordinat sisteminde geçerli olduğunu ve dünya verisine geçerken hangi API yüzeyinin devreye girdiğini netleştirir. Model parenting «hangi düğüm kime bağlansın?» sorusuna; Çoklu model runtime düğüm taşıma akışlarına odaklanır — burada aynı cümleleri yeniden kurmak yerine bu iki konuyu tamamlayan okuma sunulur.
Önerilen okuma sırası
Önce Object3D hiyerarşisi, ardından bu sayfadaki yerel/dünya ayrımı; bağlama kararları ve örnekler için parenting ile sahne grafiği metinlerine geçmek, kavramları üst üste binmeden oturtur.
Yerel ve dünya dönüşümü
A. Local transform (yerel uzay)
Objenin doğrudan bağlı olduğu ebeveyne (parent) göre olan konum, dönüş ve ölçek bilgisidir.
- Referans noktası: Ebeveynin merkezidir (0, 0, 0) — yani çocuğun
positionvektörü, ebeveynin yerel eksenlerinde tanımlıdır. - Mantık: Bir karakterin elindeki kılıç ele tam oturmuşsa, karakter dünyanın neresine giderse gitsin kılıcın yerel konumu değişmez; elin koordinat sisteminde hep aynı yerdedir.
B. World transform (dünya uzayı)
Objenin, tüm sahnenin mutlak merkezi olan sahne köküne (scene root) göre olan dönüşümüdür.
- Referans noktası: Sahnenin mutlak merkezi (0, 0, 0) ile tanımlanan dünya uzayıdır.
- Mantık: Karakter haritada koşarken elindeki kılıcın dünya konumu her karede değişir; çünkü kılıç karakterle birlikte mutlak uzayda yer değiştirir.
Sahne kökü: «nerede yerel biter?»
Bir düğümün doğrudan ebeveyni scene (veya tek kök grup) ise, o düğüm için
yerel öteleme çoğu pratikte dünya ile aynı eksenleri kullanır; yine de
rotation / quaternion / scale alanları yerel temsil
olmaya devam eder. Zincir derinleştikçe — örneğin gövde → omuz → el — «yerel»
kavramı yalnızca bir üst düğüme sıkışır; dünya ise tüm zincirin birleşik
sonucudur.
Yön uyarısı: İki nokta arasındaki offset vektörünü
düşünürken, vektörü hangi uzayda ürettiğinize dikkat edin. Aynı sayı üçlüsü, bir objenin
yerel eksenlerinde «ileri» anlamına gelirken dünyada farklı yöne dönmüş olabilir; ışın,
kuvvet veya kamera «baktığı yön» için çoğu zaman dünya uzayında normalize edilmiş yön
gerekir (getWorldDirection gibi yardımcılar).
Neden kritik? (Hata senaryoları)
Bu iki kavramı birbirine karıştırmak, çözülmesi zor mantık hatalarına yol açar.
Yanlış hesap = yanlış pozisyon. Örneğin bir lazer ışınını karakterin
silahından çıkarmak istediğinizi düşünün: silahın position değerini doğrudan
lazerin dünya başlangıcı sanırsanız, değer yalnızca silahın ebeveyne göre
ötelemesidir; dünyada nerede durduğunu söylemez. Lazerin başlangıcını dünya uzayında
kurmak için getWorldPosition veya eşdeğer bir dünya vektörü hesabı gerekir.
Animasyon ve senkronizasyon. İki farklı ebeveyne bağlı iki objeyi (örneğin iki farklı araçtaki iki karakter) birbirine göre hareket ettirirken yalnızca yerel koordinatlarla mesafe veya çarpışma kurmak yanıltıcıdır. Aralarındaki gerçek ilişkiyi kurmak için çoğu zaman her ikisinin de dünya uzayı temsiline ihtiyaç duyarsınız.
UI ve ekran uzayı. Fare isabeti, etiket
sabitleme veya seçim halesi gibi işlerde ekran / kamera ile köprü kurarken, sahne
köküne göre tutarlı bir «gerçekten nerede?» cevabı genelde dünya vektörleri üzerinden
gider; yalnızca position kopyalamak bu yüzden sık sık kayar.
Ebeveyn değişimi. Bir düğümü yeniden bağlarken (re-parent) yerel sayılar hedef ebeveyne göre yeniden yazılır; ekranda aynı yerde tutmak için dünya matrisini korumak ayrı bir iştir — bu akışın ayrıntısı runtime birleştirme metninde; burada yalnızca şu cümle yeter: yerel kolayca değişir, dünya aynı kalmak zorunda değildir.
Matematiksel arka plan: matris çarpımı
Bilgisayar grafikleri bu geçişi matris çarpımı ile modeller. Bir objenin dünya matrisi, ebeveynlerinin dünya matrisleriyle yerel model matrisinin zincirle çarpılmasıyla elde edilir:
Mworld = Mparent, world × Mlocal
Bu dönüşüm zinciri (transformation chain), ebeveyndeki en ufak bir değişikliğin alt düğümlere dalga dalga yayılmasını sağlar; Three.js de her Object3D için bu zinciri sahne grafiğinde günceller.
Zincir birden fazla ebeveyn içeriyorsa, düşünsel olarak
Mworld
=
Müst, world
× ··· ×
Mparent
×
Mlocal
biçiminde uzar; uygulamada bu çarpımı elle kurmak yerine motorun hesapladığı
matrixWorld önbelleğini okumak daha güvenlidir.
Three.js sütun vektörü düzeninde (column-vector) çalışır: bir noktayı dönüştürürken vektörü soldan matrisle çarpmayı düşünebilirsiniz. Bu sayfa matris cebirine inmez; yeter ki çarpım sırasının tersine sahne ağacında kökten uca doğru biriken bir bütün olduğunu hatırlayın.
Uygulama: Three.js yaklaşımı
Three.js’te position, rotation (veya quaternion) ve
scale alanları yerel uzayı ifade eder. Dünya verisine
geçmek için aşağıdaki yardımcıları kullanırsınız.
İhtiyaç → çözüm metodu
| İhtiyaç | Çözüm metodu |
|---|---|
| Yerel konum | object.position |
| Dünya konumu | object.getWorldPosition(targetVector) |
| Dünya dönüşü | object.getWorldQuaternion(targetQuaternion) |
| Koordinat dönüşümü | object.localToWorld(vector) veya
object.worldToLocal(vector)
|
| Dünya yönü (ör. ileri eksen) | object.getWorldDirection(targetVector) — özellikle yerel
position farkı kadar bariz olmayan yönelim hatalarında işe yarar.
|
Tablonun arkası: iki sık tuzak
localToWorldveworldToLocal, gönderdiğinizVector3örneğini yerinde günceller; yeni vektör dönmez. Aynı vektörü hem girdi hem çıktı sanıp yanlış paylaşmak yaygın bir hatadır.getWorldPosition/getWorldQuaternioniçin sahne genelinde yeniden kullanılabilir «çizgi içi»Vector3/Quaterniontutmak, döngü başınanewatmaktan daha öngörülebilir performans verir (özellikle çok sayıda düğüm okunuyorsa).
Kısa seçim kılavuzu
- Yerel: Eklem açısı, menteşe limiti, model içi ofset — yani «ebeveynin içinde, ona göre ne yapıyorum?»
- Dünya: İki ayrı dalı karşılaştırma, ışın başlangıcı, ses dinleyicisi veya kamera takibi — yani «haritada gerçekten nerede ve hangi yöne bakıyor?»
İllüstrasyon
position değeri ebeveyne göre sabit kalır; sürgü yalnızca küpü
Y ekseninde döndürür — dünya konumu satırında sayıların
değiştiğini izleyin. Tam laboratuvar değil; okuma desteği.
- Yerel
child.position - Dünya
getWorldPosition
Ayrıntılı sahne düğümü davranışı için Object3D ve sahne hiyerarşisi sayfasına bakabilirsiniz.
HoloDepth ipucu:
updateMatrixWorld
Three.js performans için dünya matrislerini her milisaniyede tek tek yeniden hesaplamaz; genelde render öncesi veya ihtiyaç duyulduğunda toplu günceller. Bir objeyi hareket ettirdikten hemen sonra, aynı kare içinde dünya konumunu okursanız, değerin henüz güncellenmemiş görünmesi mümkündür.
Çözüm: Okumadan önce ilgili alt ağaç için
object.updateMatrixWorld(true) çağrısıyla hiyerarşiyi güncellemeye zorlayın
(yalnızca gerektiğinde; her karede kökten koşullu çağrı performansı düşürür).
updateMatrixWorld(true) çağrısı, alt düğümleri de kapsayacak şekilde dünya
matrislerini tazeler; aynı karede okuma öncesi «değer neden eski kaldı?» sorununu çoğu
zaman böyle çözersiniz. Argümansız veya false ile çağrı, yalnızca güncelleme
bayrakları işaretliyse iş yapar — bu yol bazen yeterlidir, fakat hata ayıklarken önce
true ile netleştirip ardından kapsamı daraltmak pratik bir sıradır.
scene.updateMatrixWorld(true) çağrısını her karede kökten yürütmekten ise
performans için kaçının.
parent.position.x += 0.1;
// Aynı karede dünya konumu gerekiyorsa:
parent.updateMatrixWorld(true);
const worldPos = new THREE.Vector3();
child.getWorldPosition(worldPos);