holodepth

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

Channels & Samplers glTF'de Örnekleri Hedefe Bağlama

«Clip var, keyframe var, ama kemik oynamıyor» çoğu zaman bağ katmanında kopar: Keyframe Mantığı zaman–değer tablosunu tanımlar; bu sayfa ikinci soruya geçer: örnekler hangi node'un hangi özelliğine, hangi interpolasyonla gidecek?

glTF animasyonunda iki köprü vardır: sampler «zaman + değer + nasıl ara değer» üçlüsünü taşır; channel «bu sampler'ı şu node'un şu path'ine uygula» der. İkisi birlikte keyframe'i anlamlı harekete çevirir; biri eksikse dosyada veri vardır ama sahne değişmez.

Sayfayı bitirdiğinizde şu cümleyi kurabilmelisiniz: «Her channel bir sampler indeksine ve bir target (node + path) işaret eder. Sampler input/output accessor'ları keyframe'i okur; interpolation (LINEAR, STEP, CUBICSPLINE) ara değer politikasını belirler. Oynatma hâlâ runtime işidir; format yalnızca bağ sözleşmesini yazar.»

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

Bu sayfa glTF channel / sampler bağ mantığını anlatır:

  • channels[] · samplers[] indeks ilişkisi
  • target.node + target.path
  • Interpolation enum ve semantik farkları
  • CUBICSPLINE tangent düzeni (format katmanı)
  • Kanal envanteri, paylaşım, Holodepth perspektifleri

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

Kısa ayrım: Keyframe (Format) «tablo nedir?» · Channels & Samplers (Format) «kim, nasıl interpolate?» · AnimationMixer (Runtime) «sahneye nasıl uygulanır?»

Animasyon hattı ikinci soru

Katman glTF nesnesi Soru Sayfa
1 · Örnekler animations[] · zaman/değer Hareket hangi örneklerle saklanır? Keyframe Mantığı
2 · Bağ channels · samplers Örnekler nereye ve nasıl uygulanır? Channels & Samplers (bu sayfa)
3 · Deform skins · joints Kemikler geometriyi nasıl eğer? Skinning
4 · Şekil morph targets Yüz / şekil anahtarı nasıl? Morph Targets

İki sütun: sampler veri, channel hedef

Zihin modeli: kablo + priz

  • Sampler elektrik kablosu: zaman, değer, geçiş tipi taşır.
  • Channel priz: «bu kabloyu şu node'un şu yuvasına tak».
  • Clip dağıtım kutusu: birden fazla kablo + priz çifti.
  • Runtime anahtar: hangi clip'in enerjisi sahneye gidecek.

Bir animasyon clip'i içinde samplers ve channels dizileri birlikte yaşar. Sampler tek başına «kime gidecek?» bilmez; channel tek başına «hangi keyframe?» bilmez. Holodepth okuma sırası: önce sampler envanteri (kaç veri köprüsü var), sonra channel envanteri (kaç hedef bağlandı), sonra eşleşme (channel.sampler indeksi geçerli mi).

"animations": [{
  "name": "Walk",
  "samplers": [
    {
      "input": 12,
      "output": 13,
      "interpolation": "LINEAR"
    },
    {
      "input": 12,
      "output": 14,
      "interpolation": "LINEAR"
    }
  ],
  "channels": [
    {
      "sampler": 0,
      "target": { "node": 5, "path": "rotation" }
    },
    {
      "sampler": 1,
      "target": { "node": 5, "path": "translation" }
    }
  ]
}]

Örnekte iki channel aynı input accessor'ını (indeks 12) paylaşır: rotation ve translation aynı zaman çizelgesinde ilerler. Output accessor'ları farklıdır (13 vs 14) çünkü değer tipi ve anlamı farklıdır. Bu paylaşım yaygın ve geçerlidir.

Keyframe «ne zaman, ne değer?» sorusunu yanıtlar. Channel «hangi node'un hangi alanı?» sorusunu yanıtlar. Sampler «ara değer nasıl?» sorusunu yanıtlar. Üçü birlikte «hareket» olur.

Channel: target sözleşmesi

Her channel nesnesi iki alan taşır: sampler (dizin) ve target. Target iki alt alandır:

  • node: nodes[] dizisindeki hedef indeks
  • path: animate edilecek özellik adı (enum string)
Core target.path değerleri
path Node alanı Output tipi (özet)
"translation" translation VEC3
"rotation" rotation VEC4 quaternion
"scale" scale VEC3
"weights" morph ağırlıkları SCALAR dizisi

Core'da matrix path'i yoktur. Matrix-only node animate etmek için export TRS kanallarına açmalıdır; aksi halde channel hedefi bulunamaz. Statik transform anlamı Transform Verileri'ndedir; bu sayfa yalnızca «hangi path animate edilebilir» listesini sabitler.

Node indeksi geçerliliği

target.node sahnedeki gerçek bir node'a işaret etmelidir. Export'ta silinen kemik, birleştirilen rig veya yanlış indeks remap «animasyon var ama görünmüyor» üretir. Holodepth envanter sorusu: channel sayısı kadar nodes[target.node] var mı? Node adı eşleşmesi JSON'da zorunlu değildir; yalnızca indeks sözleşmesi geçerlidir. Node Hiyerarşisi ile birlikte okuyun: animate edilen node ile mesh'in skin joint listesi farklı kavramlardır (Skinning sayfası).

weights path önizlemesi

weights path'i morph target ağırlıklarını animate eder; geometri tanımı morph sayfasındadır. Burada yalnızca not: weights channel'ı olan clip, keyframe output'unun uzunluğu hedefteki morph sayısıyla uyumlu olmalıdır. Uyumsuzluk sessiz kırılma veya kısmi uygulama üretebilir.

Sampler: input, output, interpolation

Sampler üç alanla keyframe okuma politikasını tanımlar:

  • input: zaman accessor indeksi (SCALAR, saniye)
  • output: değer accessor indeksi (path'e göre tip)
  • interpolation: ara değer modu

Zaman ve değer accessor semantiği Keyframe · input/output bölümündedir. Bu sayfa «okuduktan sonra nasıl birleştirilecek» sorusuna odaklanır.

Interpolation enum

Core interpolation değerleri
Değer Davranış (özet) Tipik kullanım
LINEAR İki key arası doğrusal / slerp (rotation) Genel TRS, çoğu export
STEP Son key değeri bir sonrakine kadar sabit Discrete switch, poz değişimi
CUBICSPLINE Hermite spline; tangent verisi gerekir Az key ile yumuşak eğri

Interpolation path başına sampler'da tanımlıdır. Aynı node'un rotation'ı LINEAR, translation'ı STEP olabilir (nadir ama geçerli). Runtime her track için ayrı politika uygular; mixer bunu clip yüklerken track metadata'sından alır.

LINEAR ve STEP: iki farklı zaman hissi

LINEAR çoğu karakter hareketinin varsayılanıdır. Translation ve scale için bileşen bazlı linear interpolation; rotation için quaternion slerp beklenir (spec uyumu loader'a bağlıdır, ama hedef bu yöndedir). Seyrek key + LINEAR = köşeli hareket; dense bake + LINEAR = pürüzsüz hareket.

STEP «t anına kadar önceki değeri tut» modudur. Morph weights anahtarlaması, kapı aç/kapa pozları, UI state geçişleri için uygundur. STEP ile LINEAR'ı aynı clip'te karıştırmak bilinçli tasarımdır: gövde LINEAR yürürken yüz ifadesi STEP ile poz değiştirir.

LINEAR ≠ easing API

DCC'deki «ease in/out» eğrisi glTF'de çoğu zaman ya CUBICSPLINE tangent ya da dense LINEAR bake olarak görünür. Three.js'teki easing fonksiyonları Lerp & Easing runtime katmanıdır; dosyada easeInOutCubic alanı yoktur. Format LINEAR der; ürün kodu bunun üstüne ek politika koyabilir, ama bu dosya sözleşmesini değiştirmez.

STEP ve «hold» frame

STEP'te son keyframe değeri, bir sonraki keyframe zamanına kadar geçerlidir. Loop sınırında ilk/son key uyumsuzsa «bir karelik sıçrama» görülür; bu keyframe kenar sürekliliği sorunudur ( Keyframe · döngü sınırı), interpolation hatası değil.

CUBICSPLINE: tangent üçlüsü ve output şişmesi

CUBICSPLINE seçildiğinde output accessor düzeni değişir. Her keyframe için output'ta üç ardışık değer beklenir:

  1. in-tangent (giriş eğimi)
  2. value (asıl key değeri)
  3. out-tangent (çıkış eğimi)

Yani «3 keyframe» sandığınız output aslında 9 öğe (VEC3 için 27 float) olabilir. Holodepth: accessor count görünce önce interpolation'a bakın; aksi halde «fazla key var» yanlış teşhisi üretirsiniz.

// CUBICSPLINE, N key için output öğe sayısı = 3 × N
// translation (VEC3): her öğe 3 float → toplam 9N float
output[3*i + 0] = in_tangent_i
output[3*i + 1] = value_i
output[3*i + 2] = out_tangent_i

Tangent uzayı value ile aynı boyuttadır (VEC3 için VEC3 tangent). Rotation CUBICSPLINE'da quaternion tangent taşır; debug zordur. Export araçları bazen CUBICSPLINE'ı otomatik üretir, bazen LINEAR'a düşer; pipeline envanterinde path başına interpolation dağılımını saymak faydalıdır.

CUBICSPLINE vs dense LINEAR

Interpolasyon ticareti
Yöntem Dosya Debug Risk
Dense LINEAR Büyük Kolay Gereksiz byte
CUBICSPLINE Küçük (seyrek key) Zor Tangent / count hatası
STEP Küçük Orta Yanlış path'te köşe

İndeks bağlama: channel ↔ sampler

channel.sampler bir tam sayı indeksidir; samplers dizisindeki elemana işaret eder. Geçersiz indeks (negatif, samplers.length dışı) bozuk dosyadır. Bir sampler birden fazla channel tarafından referans alınabilir mi? Core şemada yasak değildir; pratikte nadirdir ve yan etki riski yüksektir (aynı output'un iki farklı node'a yazılması).

Yaygın desen: her (node, path) çifti için ayrı sampler, çoğu zaman aynı input'u paylaşır. Alternatif: translation/rotation/scale için üç ayrı sampler, üç ayrı channel; hepsi input 12'yi gösterir. Bu, TRS kanallarının zaman kaymasını önler.

Yetim sampler / channel

  • Channel yok, sampler var: veri taşınır ama uygulanmaz (ölü veri)
  • Channel var, sampler geçersiz: bozuk dosya
  • Channel var, target.node geçersiz: sessiz no-op veya loader hatası

Validator her yetim sampler için uyarmayabilir. Holodepth envanter: kullanılan sampler indekslerinin kümesi ile samplers.length karşılaştırması. Fazla sampler = optimizasyon fırsatı veya export artığı.

TRS kanal paketi: eksik path bilinçli olabilir

Bir kemik için üç ayrı channel beklemek yaygın bir varsayımdır; zorunluluk değildir. Yalnızca rotation animate edilip translation sabit bırakılabilir ( Keyframe · kısmi kanal). Holodepth: «eksik kanal = bozuk» demeden önce sanat niyetini sorun.

Root motion export'larında pelvis translation + bacak rotation ayrımı tipiktir. Scale kanalı çoğu karakterde hiç yoktur; varsa aynalanma veya squash animasyonu içindir. Scale + rotation birlikte animate edildiğinde pivot kayması hissedilebilir; bu transform sırası ( Transform) ile birleşen semptomdur.

Aynı node, çoklu path

Aynı target.node için translation, rotation ve scale ayrı channel'lardır. Her birinin kendi sampler'ı vardır; interpolation path başına farklı olabilir. Runtime aynı karede üç alanı günceller; sıra motor içindedir (genelde TRS birleştirme matrix'e gider). Format sıra taşımaz.

Loader köprüsü: track adı ve format sınırı

GLTFLoader channel + sampler çiftini motor track'ine çevirir: hedef node adı veya UUID, path string, keyframe dizileri, interpolation. Bu çeviri formatı değiştirmez; okunabilir API üretir. Track adlandırma loader sürümüne bağlı olabilir; ürün kodu track'i isimle değil node+path ile bulmak daha kararlıdır.

Derin oynatma, crossfade, weight Animation Clips ve AnimationMixer sayfalarındadır. Bu sayfa yalnızca «dosyada hangi bağ var» sorusunu kapatır: channel envanteri yeşil değilse mixer ayarlamak zaman kaybıdır.

Format → runtime eşlemesi (özet)
glTF Anlam Runtime (Three.js özet)
animation clip channels + samplers paketi AnimationClip
channel.target node + path track hedefi
sampler interpolation ara değer modu track interpolation
input / output keyframe verisi times / values dizileri

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

Resmi spec tabloları doğrudur; üretimde aşağıdaki ayrımlar sık görülür, az yazılır.

Doğru keyframe, yanlış node

Clip dolu, sampler LINEAR, ama target.node mesh node'una işaret ediyor; skinned karakterde hareket görünmez. Kemik animasyonu joint node'larına bağlanmalıdır. Teşhis: channel envanterinde hedef node'un skin / joint ilişkisi (Skinning ile birlikte).

Rotation flip: interpolation + quat

LINEAR quaternion interpolation kısa yol (slerp) bekler; uzun yol seçilirse veya normalize edilmemiş quat varsa 180° civarı «flip» görülür. Semptom channel/sampler katmanında başlar; çözüm çoğu zaman export quat düzeni veya CUBICSPLINE tangent tutarlılığıdır, shader değil.

Çift channel çakışması

Aynı (node, path) için iki channel aynı clip'te tanımlıysa son yazılan veya loader sırası kazanır; davranış belirsizleşir. Merge / re-export araçları bazen duplicate üretir. Envanter: (node, path) çiftlerini kümeleyin; tekrar varsa temizleyin.

Interpolation varsayılanı tuzağı

Eksik interpolation alanı spec'te LINEAR kabul edilir (uygulama uyumuna güvenin). Export bazen STEP yazar, viewer LINEAR sanar. Dosyada enum'u açık yazmak Holodepth standardıdır; «varsayılan»a güvenmeyin.

weights output uzunluğu

Morph sayısı 8 iken weights output 5 öğe taşıyorsa kısmi yüz ifadesi veya sessiz truncation olur. Channel path weights ise output accessor count ile hedef morph dizisi uzunluğunu karşılaştırın (Morph Targets sayfası geometriyi, bu sayfa bağ uzunluğunu sorar).

Altı soruluk bağ teşhisi

Channel & sampler kontrol listesi
Soru Yeşil ise Kırmızı ise bak
channel.sampler geçerli mi? Bağ var Bozuk indeks
target.node var mı? Hedef sahne içi Silinmiş kemik / remap
path core enum mu? Animate edilebilir alan Matrix-only / typo
Interpolation beklenen mi? Doğru geçiş hissi STEP/LINEAR karışıklığı
CUBICSPLINE output 3×N mi? Tangent hizalı Count / bake hatası
(node, path) tekrarı yok mu? Tek sahiplik Duplicate channel

Holodepth içgörüsü

«Keyframe doğru, sahne hareketsiz» vakalarının çoğu channel envanterinde çözülür: hedef node doğru mu, path TRS/weights mi, sampler indeksi geçerli mi, aynı (node, path) iki kez yazılmış mı? Mixer'a geçmeden önce bu dört satırı yeşile boyayın.

Bağ katmanından sonra

Örnekler hedefe bağlandıktan sonra sıradaki soru deformdur: kemik rotation channel'ı vardır ama mesh nasıl eğilir?

  1. Skinning joints, inverseBindMatrices, vertex weights
  2. Morph Targets shape keys, weights channel detayı
  3. Runtime AnimationMixer

Format okuyucusu özeti: sampler = veri + interpolasyon; channel = hedef; clip = paket. Keyframe tabloyu yazar, channel prizi takar, skinning ve morph görünür hareketi tamamlar.