3D Model Formatları · glTF / GLB · Animasyon Sistemi
Morph Targets glTF'de Şekil Anahtarı Sözleşmesi
«Gülümseme DCC'de var, web'de yüz donuk» çoğu zaman mixer eksikliği
değil; dosyada targets delta'larının veya weights kanalının
kopukluğudur.
Skinning kemikle
eğer; bu sayfa dördüncü soruya geçer:
şekil anahtarları dosyada nasıl saklanır ve hangi ağırlıkla karışır?
Holodepth Animasyon hattının son format katmanı morph'tur: primitive üzerindeki
targets[] (delta attribute setleri), mesh/node
weights (başlangıç karışımı), ve isteğe bağlı animasyon
path: "weights". Runtime
morphTargetInfluences bu sözleşmeyi API'ye çevirir;
bu sayfa dosya sözleşmesini sabitler.
Sayfayı bitirdiğinizde şu cümleyi kurabilmelisiniz: «glTF morph target, taban geometriye eklenecek delta attribute paketidir. Her target bir ağırlıkla ölçeklenir; sonuç lineer kombinasyondur. İsimler çoğu zaman extras/uzantıdadır; core zorunlu alan indeks sırasıdır. Skinning joint matrisiyle eğer, morph köşe delta'sıyla eğer; ikisi aynı mesh'te birleşebilir.»
Bu sayfanın sınırı · komşu konularla ayrım
Bu sayfa glTF morph dosya sözleşmesini anlatır:
primitives[].targets[]delta attribute'larıPOSITION/NORMAL/TANGENTdeltamesh.weights/ node weights- Animasyon
path: "weights"uzunluk sözleşmesi - Sparse accessor, isimlendirme, Holodepth teşhis açıları
Bilinçli olarak dışarıda bırakılan konular:
- Keyframe / clip → Keyframe Mantığı
- Channel path / interpolation → Channels & Samplers
- JOINTS / IBM → Skinning
- Vertex attribute genel sözlüğü → Vertex Verileri
morphTargetInfluences, dictionary, JS API, bellek bütçesi lab → Morph Targets (Three.js)- AnimationMixer / clip oynatma → AnimationMixer
Kısa ayrım: Morph Targets (Format) «delta ve weights dosyada nasıl?» · Morph Targets (Runtime) «influences nasıl yazılır?» · Skinning (Format) «kemik–köşe bağı»
Animasyon hattı dördüncü soru
| Katman | glTF nesnesi | Soru | Sayfa |
|---|---|---|---|
| 1 · Örnekler | animations[] |
Hareket hangi örneklerle saklanır? | Keyframe Mantığı |
| 2 · Bağ | channels · samplers | Örnekler nereye / nasıl uygulanır? | Channels & Samplers |
| 3 · Deform | skins · JOINTS/WEIGHTS | Kemikler geometriyi nasıl eğer? | Skinning |
| 4 · Şekil | targets · weights | Yüz / şekil anahtarı nasıl? | Morph Targets (bu sayfa) |
Morph target nedir? (Format dilinde)
Zihin modeli: taban heykel + kil yamaları
- Taban mesh nötr heykel (attributes.POSITION).
- Her target bir kil yaması: «gülümseme farkı», «göz kırpma farkı».
- Ağırlık yamanın ne kadar yapıştırılacağı (0…1, bazen dışı).
- Sonuç taban + Σ (ağırlık × delta); formül runtime'da, delta dosyada.
DCC'de «shape key / blend shape / morph» timeline kaydırıcısıdır. glTF'de karşılığı kurudur: her target, taban attribute ile aynı vertex sırasına hizalı delta accessor setidir. Absolute pozisyon kopyası değil; fark vektörüdür. Bu yüzden «hedef mesh'i ayrı GLB» sanmak yanlıştır; tek primitive içinde birden fazla delta paketi yaşar.
Morph Targets (format) şunların hiçbiri değildir:
- Skinning değil joint matrisi yok; köşe–kemik bağı Skinning'de
- Displacement texture değil doku zinciri Materyal Sistemi'nde
- morphTargetInfluences API değil Three.js Morph sayfasında
- Face rig UI / FACS paneli değil sanat aracı katmanı
- Physics soft body değil format dışı
Skinning «iskelet askısı kumaşı eğer» der. Morph «kil yaması doğrudan köşeye eklenir» der. İkisi aynı yüzde birleşebilir: kemik çeneyi açar, morph dudağı şekillendirir.
targets[]: delta paketleri
Morph verisi meshes[].primitives[].targets dizisindedir. Her eleman bir
target'tır; içinde tabanla aynı semantik anahtarlar (çoğunlukla
POSITION, isteğe bağlı NORMAL, TANGENT) accessor
indekslerine işaret eder.
"meshes": [{
"weights": [0, 0, 0],
"primitives": [{
"attributes": {
"POSITION": 0,
"NORMAL": 1
},
"targets": [
{ "POSITION": 10, "NORMAL": 11 },
{ "POSITION": 12, "NORMAL": 13 },
{ "POSITION": 14, "NORMAL": 15 }
]
}]
}]
Holodepth envanter sayıları:
- Target sayısı =
targets.length - Weights uzunluğu aynı sayıya eşit olmalı
- Vertex count taban POSITION ile her target POSITION aynı
count
Target sırası isimden önce gelir: indeks 0 «smile» olabilir veya olmayabilir; core zorunlu isim alanı yoktur. İsimleme aşağıda (§7).
Targetsiz dosya geçerlidir
Morph olmayan mesh core glTF'dir. Morph «zorunlu katman» değil; yüz / kas / ezilme ihtiyacında gelir. «Animasyon var = morph var» yanlıştır: yalnızca TRS channel'ı olan karakter morph taşımıyor olabilir.
Delta semantiği: ne taşınır?
| Anahtar | Anlam | Not |
|---|---|---|
POSITION |
Konum farkı (delta) | Neredeyse her zaman zorunlu pratik |
NORMAL |
Normal farkı | Işık tutarlılığı için önerilir |
TANGENT |
Tangent farkı | Normal map + morph birleşiminde |
Delta, «hedef mutlak pozisyon» değildir: final = base + w × delta.
Export mutlak shape yazarsa loader/glTF araçları çoğu zaman delta'ya çevirir; yanlış
kalırsa «çifte ofset» (yüz iki kat şişer) görülür. Holodepth teşhisi: ağırlık 1.0'da
beklenen şekil ile dosyadaki max displacement'i karşılaştırın.
NORMAL / TANGENT eksikliği
Yalnızca POSITION morph'lanıp NORMAL sabit kalırsa ışık «şekli takip etmez»: gölge eski yüzde kalır. Tangent eksikliği normal map'li yüzde benzer kayma üretir ( Tangent Verileri). Format geçerli olabilir; görsel kalite sözleşmesi eksiktir.
TEXCOORD / COLOR morph?
Core pratikte morph target'lar geometri (POSITION/NORMAL/TANGENT) odaklıdır. UV veya renk morph'u yaygın core path değildir; ihtiyaç varsa uzantı veya ayrı pipeline gerekir. «Albedo animasyonu morph'ta» varsayımı çoğu zaman yanlıştır.
weights: başlangıç karışımı
meshes[i].weights (ve bazı durumlarda node üzerindeki weights) her
target için başlangıç ağırlığını verir. Uzunluk = target sayısı. Eksik weights çoğu
loader'da sıfır dizi varsayılır (nötr yüz).
- Hepsi 0: taban şekil (Idle yüz)
- Bir tanesi 1: o target tam uygulanmış
- Birden fazla > 0: lineer karışım (smile + blink)
Ağırlık aralığı pratikte 0…1'dir; spec dışına çıkan değerler (negatif, >1) abartılı veya ters morph üretebilir. Ürün kodu clamp edebilir; dosya sözleşmesi her zaman clamp demez.
Statik weights vs animate weights
Mesh.weights «dosya açılış pozu»dur. Animasyon
target.path === "weights" kanalı zaman içinde bu diziyi ezer (
Channels · weights path). Mixer yoksa yalnızca statik
weights görülür; «morph animate olmuyor» teşhisinde önce channel var mı sorun.
Animasyon: path: "weights"
Morph animasyonu ayrı bir «yüz klibi formatı» değildir; aynı
animations[] içinde weights path'li channel'dır. Sampler output'u
tipik olarak her keyframe'de tüm target ağırlıklarını sıralı yazar.
// Kavramsal: M target için her keyframe M SCALAR
output keyframe k: [w0, w1, …, w(M-1)]
// accessor count ≈ keyframeSayısı × M (CUBICSPLINE'da 3× faktör)
Holodepth uzunluk kuralı: output'taki morph boyutu =
targets.length. 8 target varken output 5 öğe taşıyorsa kısmi ifade
veya truncation oluşur (
Channels · weights uzunluğu). Tersi (fazla öğe)
tanımsız artıktır.
Channel target.node
Weights channel'ı morph'lu mesh'i taşıyan node'a (veya weights'in uygulandığı node'a) işaret etmelidir. Yanlış node indeksi «clip var, yüz oynamıyor» üretir; skinning'deki yanlış joint node tuzağının morph yüzüdür.
Interpolation ve yüz
LINEAR ağırlık geçişi yumuşak mimik verir; STEP ani ifade değişimi (karikatür / UI state) içindir. CUBICSPLINE yüz kanallarında da mümkündür; output düzeni 3× şişer ( Channels · CUBICSPLINE). Easing API dosyada yoktur; dense LINEAR veya CUBICSPLINE ile yaklaşılır.
Sparse accessor: seyrek delta
Bir gülümseme çoğu köşeyi sıfır bırakıp yalnızca ağız çevresini hareket ettirir. glTF sparse accessor ile yalnızca değişen indeksleri ve değerlerini saklayabilir; geri kalan taban (veya sıfır) varsayılır. Bu, morph binary'sini küçültmek için kritik Holodepth üretim aracıdır.
- Kazanç: yüz / kas morph'larında ciddi boyut düşüşü
- Risk: sparse bozulursa yanlış köşe kayar; debug zorlaşır
- Teşhis: accessor.sparse var mı, count ile indices uyumlu mu?
Sparse mekanizmasının genel okuması Accessor / BufferView hattındadır; burada «morph için neden sık kullanılır?» sorusu sabitlenir. Draco geometriyi sıkıştırır; morph delta'ları ayrı kalır; sparse morph boyutu için birincil format içi çözümdür.
İsimlendirme: indeks önce, isim sonra
Core glTF target'lara zorunlu name vermez. İsimler pratikte:
mesh.extras.targetNames(yaygın extras sözleşmesi)- Vendor / DCC uzantı alanları
- Loader'ın ürettiği dictionary (runtime)
Ürün kodu influences[dict["smile"]] ile isimden giderse extras
kaybında kırılır. Holodepth: export sonrası isim listesini doğrulayın; yoksa indeks
sözleşmesini dokümante edin. Material Slots / clip name tuzağının morph yüzü budur.
Sıra kararlılığı
Target sırası DCC export sırasına bağlıdır. «smile» indeksi 2 iken yeniden export'ta 5 olabilir. Animate weights output sırası target sırasına kilitlidir; isim değil indeks hizası bozulursa yanlış mimik çalar. Pipeline'da target sırasını kilitleyin veya isim→indeks map'ini her build'de yeniden üretin.
Morph vs skinning: aynı mesh, iki deform
| Soru | Morph | Skinning |
|---|---|---|
| Veri birimi | Delta attribute | JOINTS / WEIGHTS + IBM |
| Kontrol | weights skaleri | Joint node TRS |
| Tipik kullanım | Yüz, kas, ezilme | Vücut, uzuv |
| Animasyon path | weights |
translation / rotation / scale |
Aynı primitive hem targets hem JOINTS taşıyabilir. Uygulama sırası runtime/shader sözleşmesidir (genelde morph sonra skin veya tersi; motora bakın). Format sıra taşımaz. Teşhis: yüz bozuk → morph; kol bozuk → skin; ikisi birden → her iki envanteri ayrı yeşile boyayın.
Derin runtime karşılaştırma ve kod örnekleri Three.js Morph · vs skeletal tablosundadır; burada yalnızca dosya ayrımı sabitlenir.
Holodepth perspektifleri çoğu dokümanda olmayan açılar
«targets + weights» listesi üretim teşhisini yarım bırakır. Aşağıdakiler sık, az yerde derin işlenir.
Vertex count uyuşmazlığı
Target POSITION count ≠ taban count bozuk dosyadır. Export LOD veya decimate sonrası morph'u güncellemeyi unutursa oluşur. Semptom: loader reddi veya çöplük geometri.
Çifte delta / mutlak shape
Mutlak shape yanlışlıkla delta sanılırsa ağırlık 0.5'te bile aşırı şişme görülür. Tersine delta iki kez çıkarılmışsa morph «ters yönde» gider. DCC export seçeneklerinde «relative / absolute» anahtarına bakın.
Target şişkinliği
100+ shape key web için pahalıdır: her target vertex × float × attribute. Sparse yardımcı olur; yine de CPU/GPU morph slot limiti runtime'dadır ( Three.js · morph bütçe). Format tarafı: hangi target'lar gerçekten kullanılıyor? Kullanılmayanları dosyadan çıkarın.
Primitive başına targets
Çoklu primitive mesh'te (Material Slots) her primitive kendi targets dizisine sahip olabilir. Yüz primitive'inde morph var, gövde primitive'inde yok: geçerlidir. Tek weights kanalının hangi node/mesh'e gittiğini netleştirin; yanlış primitive'e bağlanan channel sessiz no-op üretir.
Draco + morph
Draco taban geometriyi sıkıştırır; morph target'ların Draco ile birlikte nasıl taşındığı uzantı / araç zincirine bağlıdır. «Draco açtım, morph kayboldu» semptomu sık pipeline bug'ıdır. Holodepth: compress sonrası targets.length ve weights animasyonunu yeniden doğrulayın ( Draco Mesh Compression).
Altı soruluk morph teşhisi
| Soru | Yeşil ise | Kırmızı ise bak |
|---|---|---|
targets.length > 0? |
Şekil anahtarı var | Export / yanlış mesh |
| Target POSITION count = taban? | Hiza tamam | LOD / decimate kayması |
| weights uzunluğu = target sayısı? | Karışım tanımlı | Eksik / fazla dizi |
| weights channel output boyutu uyumlu mu? | Animate edilebilir | Kısmi mimik / truncation |
| Channel target.node doğru mu? | Doğru mesh güncellenir | Yanlış node / primitive |
| NORMAL (ve gerekirse TANGENT) delta var mı? | Işık şekli takip eder | Gölge kayması |
Holodepth içgörüsü
Morph debug'unda önce morphTargetInfluences'a değil
targets + weights uzunluğu + weights channel üçlüsüne bakın.
Üçü yeşilse sorun runtime API veya mixer'dadır; biri kırmızıysa dosya
sözleşmesi bozuktur. Skin yeşil + morph kırmızı = «vücut oynar, yüz donuk»
klasik vakasıdır.
Animasyon Sistemi kapanır; sıradaki dallar
Format Animasyon omurgası dört soruyla tamamlandı: keyframe → channel/sampler → skinning → morph. Sıradaki Holodepth dalları:
- Uzantılar grubu Draco, Basis, GPU instancing (tek uzantı derin sayfalar)
- Runtime morph API Morph Targets (Three.js)
- Runtime skin Skinning System
- Oynatma AnimationMixer
Format okuyucusu özeti: targets = delta paketleri; weights = karışım; path weights = zamanlı karışım. Skin askıyla eğer, morph yamayla eğer; ikisi birlikte karakteri tamamlar.