holodepth

3D Model Formatları · glTF / GLB · Animasyon Sistemi

Skinning glTF'de Kemik–Köşe Deform Sözleşmesi

«Clip oynuyor, kemikler dönüyor, mesh donuk kalıyor» çoğu zaman channel eksikliği değil, skin katmanının yokluğu veya kopukluğudur. Channels & Samplers node TRS'ini günceller; bu sayfa üçüncü soruya geçer: köşe noktaları kemik hareketini dosyada nasıl bilir?

Holodepth Animasyon hattında skinning, format tarafında üç parçanın birleşimidir: skins[] (joint listesi + inverse bind), primitive üzerindeki JOINTS_* / WEIGHTS_* öznitelikleri, ve mesh/node'un skin indeksi. Runtime SkinnedMesh / Skeleton bu sözleşmeyi sahneye çevirir; bu sayfa dosyadaki sözleşmeyi sabitler.

Sayfayı bitirdiğinizde şu cümleyi kurabilmelisiniz: «glTF skin bir joint node dizisi ve her joint için bir inverseBindMatrix taşır. Köşeler JOINTS/WEIGHTS ile bu dizideki slotlara bağlanır. Animasyon joint node TRS'ini hareket ettirir; deform formülü bind pozu ile canlı pose arasındadır. Skin olmadan channel yalnızca boş hiyerarşi döner.»

Bu sayfanın sınırı · komşu konularla ayrım

Bu sayfa glTF skinning dosya sözleşmesini anlatır:

  • skins[]: joints, inverseBindMatrices, skeleton
  • JOINTS_0 / WEIGHTS_0 (ve _1) semantiği
  • mesh / node ↔ skin indeksi
  • Bind pose, joint indeksi vs node indeksi ayrımı
  • 4-bone limit, Holodepth teşhis açıları

Bilinçli olarak dışarıda bırakılan konular:

Kısa ayrım: Skinning (Format) «dosyada kemik–köşe bağı nedir?» · Skinning System (Runtime) «SkinnedMesh nasıl deforme eder?» · Channels «joint node nasıl animate edilir?»

Animasyon hattı üçü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 (bu sayfa)
4 · Şekil morph targets Yüz / şekil anahtarı nasıl? Morph Targets

Skinning nedir? (Format dilinde)

Zihin modeli: iskelet askısı + kumaş düğmeleri

  • Joint node askı çubuğu: TRS ile hareket eder.
  • Inverse bind «kumaş bu askıya nasıl gerildi?» ölçüsü.
  • JOINTS / WEIGHTS her kumaş noktasının hangi askılara, ne kadar tutunduğu.
  • Channel askıyı döndürür; skin kumaşı askıya bağlar.

DCC'de skinning «paint weight + bind» sürecidir. glTF'de süreç bitmiş sonuçtur: hangi köşenin hangi joint slotuna hangi ağırlıkla bağlı olduğu binary'de durur; paint brush yoktur. Bu yüzden web'de weight düzeltemezsiniz; yeniden export gerekir.

Skinning şunların hiçbiri değildir:

  • Keyframe tablosu değil hareket örnekleri Keyframe sayfasında
  • Channel path değil «rotation'a yaz» Channels sayfasında
  • Morph shape değil delta pozisyon Morph Targets'ta
  • SkinnedMesh API değil Three.js Skinning System sayfasında
  • Physics / cloth sim değil format dışı

Channel «kemik nereye gitti?» der. Skin «köşe o kemiği ne kadar dinliyor?» der. İkisi olmadan karakter ya boş hiyerarşi döner ya da donuk mesh kalır.

skins[]: joint kataloğu

Kök JSON'daki skins dizisinin her elemanı bir iskelet tanımıdır. Tipik alanlar:

"skins": [{
  "name": "Character_Armature",
  "joints": [2, 3, 4, 5, 6, …],
  "inverseBindMatrices": 42,
  "skeleton": 1
}]
  • joints: nodes[] indekslerinin sıralı listesi (joint slot sırası)
  • inverseBindMatrices: MAT4 accessor indeksi; uzunluk = joints uzunluğu
  • skeleton (isteğe bağlı): ortak kök node indeksi (armature root)

Holodepth kritik ayrım: joint slot indeksi (0…N−1, joints dizisindeki konum) ile node indeksi (nodes[] içindeki gerçek numara) aynı şey değildir. JOINTS_0 attribute'u joint slot yazar; channel target.node ise node indeksidir. Karıştırmak «yanlış kemik dönüyor» semptomunun bir numaralı nedenidir.

Skinsiz dosya geçerlidir

Statik prop'larda skins yoktur. Skin «zorunlu katman» değil; karakter / organik deform ihtiyacında gelir. «Animasyon var = skin var» da yanlıştır: root node translation animate edilebilir, skin olmadan mesh katı taşınır.

Inverse bind matrices: bind pozu sözleşmesi

Bind pose, mesh'in «giydirildiği» referans pozudur. Her joint için bir inverse bind matrix (IBM), o joint'in bind anındaki dünya (veya skin uzayı) transformunun tersidir. Deform formülünün özü:

// Kavramsal (runtime uygular; dosya matrisi taşır)
skinned = Σ (weight_i × jointMatrix_i × IBM_i × bindPosition)

Dosya yalnızca IBM accessor'ını taşır; canlı jointMatrix her karede node hiyerarşisinden hesaplanır. IBM yanlışsa (yanlış uzay, yanlış sıra, eksik joint) mesh «patlar», «içe çöker» veya bind'den asla çıkmaz. Bu semptomlar channel keyframe'inden bağımsızdır: Idle clip bile bozuk IBM ile çöker.

Count uyumu

inverseBindMatrices accessor count = joints.length olmalıdır. Eksik veya fazla IBM bozuk dosyadır. Accessor tipi MAT4, bileşen tipi tipik FLOAT'tur. Accessor Mantığı okuma kurallarını verir; bu sayfa «neden MAT4 dizisi?» sorusunu sorar.

Bind vs rest vs t0

Bind pose export anındaki skin referansıdır. Rest pose node'ların statik TRS'idir. Clip'in t=0 keyframe'i üçüncü bir poz olabilir. Üçü hizasızsa oynatma başında «bir kare snap» görülür ( Keyframe · rest pose). Skinning teşhisinde önce IBM bütünlüğüne, sonra rest/t0 hizasına bakın.

JOINTS_* / WEIGHTS_* öznitelikleri

Skinned primitive'in attributes haritasında en az bir çift bulunur:

Skinning vertex attribute özeti
Attribute Tip (tipik) Anlam
JOINTS_0 VEC4 (UNSIGNED_BYTE / SHORT) Joint slot indeksleri (en fazla 4)
WEIGHTS_0 VEC4 float Ağırlıklar; genelde toplam ≈ 1
JOINTS_1 / WEIGHTS_1 aynı Ek 4 etki (8-bone); opsiyonel

Genel attribute sözlüğü Vertex Verileri'ndedir; burada semantik netleşir: JOINTS değeri skin.joints dizisindeki sıra numarasıdır, node indeksi değildir. WEIGHTS_0.x, JOINTS_0.x slotuna aittir; bileşen hizası bozulursa yanlış kemik «yağlanır».

Ağırlık toplamı

Pratikte köşe başına ağırlıklar normalize edilir (toplam 1). Spec her validator'un aynı sıkılığı uygulamaz; 0.97…1.03 aralığı yaygındır. Sıfır toplamlı köşe «hiçbir kemiğe bağlı değil» demektir: o köşe bind'de donar veya orijine çöker. Holodepth envanter: WEIGHTS sum histogramı (pipeline tool) bozuk paint'i erken yakalar.

4-bone (VEC4) limiti

Core pratikte köşe başına 4 joint etkisi (JOINTS_0) standarttır. Daha fazla etki için JOINTS_1 gerekir; birçok runtime yalnızca _0'ı garanti eder. Export «8 influence» DCC ayarı web'de sessizce 4'e kırpılabilir: omuz/kalça kırışması artar. Bu, Three.js kemik limiti anlatımının (Skinning System · kemik limiti) format yüzüdür: dosyada kaç set attribute var?

Mesh / node ↔ skin indeksi

Skin'i mesh'e bağlayan tipik yol: bir nodes[i] hem mesh hem skin indeksi taşır. Skin indeksi skins[] elemanına işaret eder. Primitive attributes JOINTS/WEIGHTS taşımazsa skin indeksi anlamsızlaşır; JOINTS varsa ama node.skin yoksa loader skinned mesh üretemeyebilir.

"nodes": [{
  "name": "Body",
  "mesh": 0,
  "skin": 0
}]

Bir dosyada birden fazla skin olabilir (ayrı ekipman, ayrı karakter). Aynı skin'i paylaşan birden fazla mesh de mümkündür (LOD, giysi katmanı). Holodepth: «kaç skin?» ile «kaç skinned mesh node?» sayılarını ayrı raporlayın.

skeleton alanı

İsteğe bağlı skeleton, joint hiyerarşisinin ortak köküne işaret eder. Runtime iskeleti bu kökten gezinebilir. Eksikliği her zaman hata değildir; joints listesi yeterlidir. Yanlış skeleton kökü helper çiziminde veya pose reset'te sapma üretir; deform formülünün kendisi joints + IBM + weights üçlüsüne dayanır.

Skin vs channel: iki farklı «kemik» dili

Animasyon channel'ı joint node'unun TRS'ini yazar. Skin, köşeleri joint slot'larına bağlar. Aynı fiziksel kemik iki dilde yaşar:

Channel ve skin karşılaştırma
Soru Channel Skin
Kim hareket eder? target.node (node indeksi) Joint slot → joints[slot] → node
Ne değişir? Node TRS Köşe pozisyonu (deform)
Veri nerede? samplers output IBM + JOINTS/WEIGHTS
Yoksa ne olur? Kemik dönmez Mesh dönmez / katı kalır

Holodepth teşhis cümlesi: «SkeletonHelper dönüyor, yüzey duruyor» → skin / weights sorunu. «Yüzey de helper da duruyor» → channel / clip sorunu. «Yüzey patlıyor» → IBM / slot indeksi sorunu.

Export: bind, kırpma, kayıp

DCC'deki IK, constraint ve control bone'lar glTF'e çoğu zaman bake edilmiş joint TRS + sabit skin weights olarak düşer ( Keyframe · bake). Skin weights bake edilmez: paint sonucu olduğu gibi taşınır (veya influence limiti ile kırpılır).

  • Apply bind atlanursa IBM ile mesh uzayı uyuşmaz
  • Non-deformer bone joints listesine girerse boş slot şişer
  • Mirror / negatif scale IBM ve normal/tangent ile birleşir ( Tangent notu)
  • Çoklu armature yanlış skin indeksine bağlanırsa yanlış iskelet giydirilir

FBX→glTF dönüşümünde joint sırası değişebilir; JOINTS indeksleri eski sıraya göre kaldıysa patlama görülür. Holodepth: dönüşüm sonrası joints sırası + IBM count + max(JOINTS) < joints.length üçlüsünü doğrulayın.

Loader köprüsü: format sınırı

GLTFLoader skins + JOINTS/WEIGHTS + node.skin üçlüsünü SkinnedMesh + Skeleton + Bone ağacına çevirir. Bu çevirinin API yüzü Skinning System sayfasındadır. Format okuyucusu için yeterli soru: dosyada skin var mı, attributes tam mı, IBM count uyumlu mu, joint slot aralığı geçerli mi?

Format → runtime eşlemesi (özet)
glTF Anlam Runtime (Three.js özet)
skins[] Joint kataloğu + IBM Skeleton
joints[] → nodes Kemik hiyerarşisi Bone ağacı
node.mesh + node.skin Giydirilmiş mesh SkinnedMesh
JOINTS / WEIGHTS Köşe bağları skin attributes / GPU

Holodepth perspektifleri çoğu dokümanda olmayan açılar

«Skinning = weights» özeti üretim teşhisini yarım bırakır. Aşağıdakiler sık, az yerde derin işlenir.

Root motion vs skinned walk

Karakter «yürüyor» sanılır ama yalnızca root node kayıyorsa ayaklar kayar (slide). Skin + bacak joint channel'ları yoksa bu beklenen davranıştır. Keyframe sayfasındaki «mesh animate olmuyor» notunun tamamlayıcısı: skin var mı, bacak joint'leri channel hedeflerinde mi?

Joint slot taşması

JOINTS değeri ≥ joints.length ise tanımsız erişimdir. Export hatası veya joints listesi kısaltması sonrası artığından kalır. Validator kaçırabilir; max(JOINTS) taraması Holodepth envanterinin parçası olmalıdır.

Paylaşılan skin, farklı mesh

Giysi ve beden aynı skin'i paylaşırsa tek iskelet iki yüzeyi eğer. Ayrı skin + ayrı armature ise iki iskelet senkronu gerekir (çift clip veya retarget). Format ikisini de destekler; ürün senkron politikası runtime'dadır.

JOINTS var, skin yok

Bazı bozuk export'lar attribute bırakıp node.skin yazmaz. Dosya «skinned gibi» görünür ama loader static mesh üretir. Tersine skin var, JOINTS yok: boş deform. İki yönlü tutarlılık şarttır.

TBN + skin

Skinning pozisyonu eğer; normal/tangent de joint matrisleriyle dönmelidir. Yalnızca POSITION skinlenip TBN sabit kalırsa ışık «yüzeyde kayar». Format attribute seti tam olsa bile runtime shader yolu eksik olabilir; teşhiste format mı shader mı ayırın ( Tangent Verileri ).

Altı soruluk skin teşhisi

Skinning katmanı kontrol listesi
Soru Yeşil ise Kırmızı ise bak
skins.length > 0? İskelet tanımı var Export / yanlış asset
node.skin + JOINTS/WEIGHTS? Giydirme tam Tek taraflı kopukluk
IBM count = joints? Bind hizalı Patlama / çökme
max(JOINTS) < joints.length? Slot geçerli OOB / remap
WEIGHTS toplamı ≈ 1? Paint sağlıklı Donuk / uçan köşe
Joint node'lar channel hedefi mi? Hareket → deform zinciri Yalnızca root / yanlış node

Holodepth içgörüsü

Skinning debug'unda önce shader'a veya mixer'a değil üçlü sözleşmeye bakın: skins.joints + IBM, JOINTS/WEIGHTS, node.skin. Üçü yeşilse sorun runtime/GPU yolundadır; biri kırmızıysa dosya sözleşmesi bozuktur. Channel yeşil + skin kırmızı = «kemik dönüyor, deri duruyor» klasik vakasıdır.

Skinning'den sonra

Kemik–köşe bağı netleşince sıradaki format sorusu şekil anahtarlarıdır:

  1. Morph Targets delta geometri, weights channel
  2. Runtime deform Skinning System
  3. Oynatma AnimationMixer

Format okuyucusu özeti: skin = joint kataloğu + IBM; köşe = JOINTS/WEIGHTS; node.skin = giydirme bağı. Channel askıyı döndürür, skin kumaşı tutturur.