holodepth

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

Keyframe Mantığı glTF'de Zaman Örnekli Hareket

«Animasyon var ama dosyada AnimationMixer yok» diye şaşırıyorsanız doğru yerdesiniz: glTF hareketi çalmaz, örnekler. Materyal Sistemi yüzey kartını kapattı; Animasyon Sistemi'nin ilk sorusu şudur: zaman ekseninde hangi değerler saklanır?

Holodepth Animasyon hattında dört katman vardır: keyframe (bu sayfa) zaman–değer örneklerini tanımlar; channels & samplers hangi node/özelliğe gideceğini bağlar; skinning kemik ağırlıklarıyla geometriyi deform eder; morph targets şekil anahtarlarını taşır. Bu sayfa yalnızca birinci katmanı sabitler: dosyada «klip» ve «kare» ne demektir.

Sayfayı bitirdiğinizde şu cümleyi kurabilmelisiniz: «glTF animations[] bir veya daha fazla clip taşır. Her clip, sampler'lar üzerinden zaman (input) ve değer (output) accessor'larına bağlı keyframe dizileridir. Oynatma, interpolasyon ve mixer runtime işidir; format yalnızca örnekleri ve hedefleri taşır.»

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

Bu sayfa glTF keyframe / clip mantığını anlatır:

  • Keyframe = zaman + değer örneği
  • animations[] clip konteyneri
  • Zaman alanı (saniye), örnek seyrekliği
  • Değer tipleri (TRS, ağırlık) özeti
  • Format vs oynatma ayrımı; Holodepth perspektifleri

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

Kısa ayrım: Keyframe Mantığı (Format) «zaman–değer tablosu nedir?» · Channels & Samplers «kim, nasıl interpolate?» · AnimationMixer (Runtime) «sahneye nasıl uygulanır?»

Animasyon hattı birinci soru

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

Keyframe nedir? (Format dilinde)

Zihin modeli: metronom + ölçü notası

  • Zaman (input) metronom vuruşu: kaçıncı saniye?
  • Değer (output) o anda çalınacak nota: konum, dönüş, ölçek…
  • Keyframe çifti bir vuruşta hangi notanın basılacağı.
  • Çalgıcı (runtime) vuruşlar arasında nasıl geçileceğini bilir; partisyon (dosya) yalnızca notaları yazar.

Animasyon yazılımında «keyframe» çoğu zaman timeline UI karesidir: kırmızı nokta, Bezier kolu, easing eğrisi. glTF'de karşılığı daha kurudur: monoton artan zaman dizisi ile hizalı değer dizisi. İkisi de binary buffer'da accessor üzerinden okunur; JSON yalnızca indeksleri ve semantiği taşır. UI'daki Bezier kolu dosyaya çoğu zaman ya bake edilmiş ara örnekler ya da CUBICSPLINE tangent verisi olarak düşer; «edit edilebilir eğri» olarak kalmaz.

Bu ayrım bilerek serttir. Interchange formatı taşıma sözleşmesidir: her motor aynı UI'yi yeniden çizmez; aynı örneklenmiş hareketi yeniden üretir. Holodepth bu yüzden keyframe'i «sanat aracı» değil «taşıma birimi» olarak okur.

Keyframe Mantığı şunların hiçbiri değildir:

  • FPS / ekran karesi değil render döngüsü ayrı sayfada
  • Easing fonksiyonu API'si değil interpolasyon sampler'da, uygulama runtime'da
  • Skeleton rig UI değil skinning sonraki sayfa
  • Physics / ragdoll değil format dışı
  • State machine / blend tree değil ürün kodu katmanı

Örnek, formül değil

Birçok motor iç dünyasında «t anında f(t)» formülü vardır (sinüs sallanma, spring, procedural walk). glTF core bu formülleri taşımaz. Export anında formül bir kez değerlendirilir; sonuç zaman–değer tablosu olur. Web'de aynı salınımı parametrik tutmak istiyorsanız ya runtime'da yeniden üretirsiniz ya da bake edilmiş tabloyu oynatırsınız. İkisi farklı ürün kararıdır; dosya yalnızca ikincisini bilir.

Geometri «nerede duruyor?» sorusunu yanıtlar. Keyframe «zaman içinde nerede olacak?» sorusunun örneklenmiş cevabını taşır. Aradaki yumuşak geçiş dosyada formül değil, çoğu zaman sampler interpolasyon tipidir.

animations[]: clip konteyneri

Kök JSON'daki animations dizisinin her elemanı bir animasyon klibidir: isteğe bağlı name, samplers listesi, channels listesi. Bir dosyada birden fazla clip olabilir («Idle», «Walk», «Attack»). Clip'ler birbirinden bağımsızdır; hangisinin çalacağı runtime seçimidir. Format «şu anda Idle çal» demez; yalnızca «Idle diye bir clip var» der.

"animations": [
  {
    "name": "Walk",
    "samplers": [ /* zaman ↔ değer köprüleri: sonraki sayfa */ ],
    "channels": [ /* hedef node + path: sonraki sayfa */ ]
  },
  {
    "name": "Idle",
    "samplers": [ … ],
    "channels": [ … ]
  }
]

Holodepth envanterinde üç sayı bilinçli ayrılır:

  • Animasyon var mı? animations.length > 0
  • Kaç hareket çeşidi? clip sayısı (dizinin uzunluğu)
  • Kaç kanal? her clip içindeki channels.length (aynı Walk klibinde onlarca kemik kanalı olabilir)

«Dosyada 1 animasyon var» demek «tek kanal» demek değildir. Tersine «80 kanal» demek «80 clip» demek değildir. Raporlarda bu üç sayıyı ayrı yazın; aksi halde sanatçı / mühendis konuşması birbirini kaçırır.

Animasyonsuz dosya geçerlidir

animations yokluğu hata değildir: statik mesh core glTF'dir. Animasyon «zorunlu katman» değil, isteğe bağlı zenginleştirmedir; tıpkı materyal uzantıları gibi, ama burada sözleşme core'dadır (ayrı KHR adı gerekmez). Bu yüzden «animasyonsuz GLB geçersiz» varsayımı yanlıştır; ürününüz yalnızca hareketli asset kabul ediyorsa bu ürün kuralıdır, format kuralı değil.

Clip = ürün SKU'su

Holodepth üretim dilinde her clip bir SKU gibidir: isim, süre, hedef kemik seti, dosya içi bayt maliyeti. Katalogda «Walk_Loop_01» ile «Walk» iki farklı SKU'dur; indekse güvenmek stok kaydını karıştırır. Material Slots'taki materyal indeksi tuzağının animasyon yüzü budur: export sırası değişince «üçüncü clip» artık Attack değil Idle olabilir.

Zaman alanı: saniye ve monotonluk

Sampler input accessor'ı tipik olarak SCALAR float zamanlardır; birim saniyedir (frame numarası değil). Değerler genelde 0'dan başlar ve sıkı artan (strictly increasing) olmalıdır. Aynı zaman damgasının tekrarı veya geriye gidiş belirsiz interpolasyon üretir; loader davranışı tanımsız kalabilir.

  • Süre ≈ son input − ilk input (clip uzunluğu)
  • Yoğun örnekleme yüksek frekanslı hareket, büyük binary
  • Seyrek örnekleme küçük dosya; ara değerler interpolasyona kalır

Export «her frame 60 FPS bake» yaptığında input dizisi şişer. Sanatçı timeline'ında seyrek key, export'ta dense bake görmek yaygındır. Holodepth: dosya boyutu analizinde animasyon accessor byteLength'ini ayrı kalem olarak sayın. Çoğu «ağır GLB» aslında yoğun keyframe'dir, texture değil.

t = 0 sözleşmesi

Birçok clip 0.0'da başlar; zorunluluk değil, pratiktir. Bazı export'lar sahne zaman çizelgesinden absülüt saniye bırakır (ör. 12.4 … 14.1). Runtime çoğu zaman clip'i kendi başına «yeniden sıfırlar»; bazen de absülüt aralığı korur. Holodepth teşhisi: input'un min/max'ına bakın. Beklenmeyen offset «geç başlıyor / hiç oynamıyor» semptomunu üretebilir.

FPS ile karıştırmayın

Ekranın 60 Hz yenilenmesi ile keyframe örnek hızı aynı şey değildir. Runtime 60 FPS çizerken 10 Hz keyframe'leri interpolate edebilir. Format zamanı süreklidir; kare bütçesi Animasyon Döngüsü konusudur. «Animasyon 30 FPS export ettim, sahnem 60 FPS» cümlesi iki farklı saati aynı cümlede birleştirir; format saati saniyedir.

Döngü sınırı dosyada yok

Seamless loop için ilk ve son keyframe değerlerinin birbirine yakın olması sanat sözleşmesidir; glTF «bu clip loop'lanabilir» bayrağı taşımaz. Son kare ile ilk kare arasında ani sıçrama varsa, loop açıkken «tık» görünür. Bu, mixer loop hatası değil, örnek tablosunun kenar süreksizliğidir.

Değer alanı: ne animate edilir?

Output accessor tipi, hedefin path'ine göre değişir. Bu sayfada yalnızca değer ailesi özetlenir; path/channel eşlemesi sonraki sayfadadır. Amaç: keyframe okurken «bu float dizisi neyi temsil ediyor?» sorusunu cevaplamak.

Tipik output semantiği
Hedef (özet) Accessor tipi Anlam
translation VEC3 Konum (x,y,z)
rotation VEC4 Quaternion (x,y,z,w)
scale VEC3 Ölçek
weights SCALAR dizisi Morph ağırlıkları (Morph sayfası)

Quaternion keyframe'lerde «Euler timeline» beklemeyin: glTF dönüşü quat olarak saklar. DCC Euler gösterir; export quat'a çevirir. Yanlış w işareti veya normalize edilmemiş quat «flip» semptomu üretir; çoğu zaman sampler interpolasyon tipi (LINEAR vs CUBICSPLINE) ile birleşir. Detay Channels sayfasındadır.

Core'da animate edilmeyenler

Materyal factor'ları, ışık şiddeti, kamera FOV, texture offset gibi alanlar core animasyon path'i değildir. Bunlar ya uzantı + özel pipeline ile gelir ya da runtime'da ayrı animate edilir. «Albedo animasyonu GLB'de neden yok?» sorusunun cevabı çoğu zaman «core path yok»tur, loader bug'ı değil.

TRS vs matrix

Node transform Transform Verileri'nde ya TRS ya matrix'tir. Animasyon genelde TRS kanallarını hedefler. Matrix-only node'u animate etmek pipeline'da TRS'e açmayı gerektirir; format tarafında «matrix animate eden core path» yoktur. Export'ta matrix node + animasyon kombinasyonu sessizce TRS'e çevrilmiş olabilir; bu dönüşüm kaybı (shear vb.) ayrı bir pipeline riskidir.

Input / output çifti (kavram)

Her sampler bir input ve bir output accessor indeksine işaret eder. Keyframe mantığının kalbi şudur:

input[i]  = t_i          // saniye
output[i] = value_i      // VEC3 / VEC4 / …
// i = 0 … count-1
// t_i sıkı artar; value_i aynı sırada hizalıdır

count uyuşmazlığı (zaman 10 örnek, değer 9) bozuk dosyadır. Bu tutarlılık Accessor katmanında doğrulanır; animasyon sayfası «neden iki accessor?» sorusunu sorar: çünkü zaman ile değer farklı tip ve anlam taşır, tek interleaved «keyframe struct» core'da yoktur.

CUBICSPLINE interpolasyonda output düzeni üçlü (in-tangent, value, out-tangent) olabilir; bu, «basit keyframe» sayısını şişirir. Holodepth: dense binary görüp «çok key var» demeden önce interpolasyon tipine bakın. Bu, Channels & Samplers sayfasının konusudur.

Paylaşılan zaman ekseni

Aynı clip içinde birçok sampler aynı input accessor'ını paylaşabilir: tüm TRS kanalları ortak zaman çizelgesine oturur. Bu hem bayt kazandırır hem de kanallar arasında zaman kaymasını önler. Tersine, her kanalın kendi zaman dizisi varsa «aynı clip, farklı ritim» mümkün olur; teşhiste input indekslerinin özdeş olup olmadığına bakın.

min / max ipucu

Accessor min / max alanları animasyonda pratik teşhis aracıdır: input max ≈ clip süresi; translation max sahne ölçeğini ifşa eder. Eksik min/max zorunlu değildir ama Holodepth envanterinde «süre ve genlik» özetini hızlandırır.

Format saklar, runtime çalar

glTF dosyasında loop, ping-pong, blend weight, crossfade yoktur (core). Bunlar player / mixer politikasıdır. Dosya «Walk klibi 1.2 sn, şu keyframe'ler» der; uygulamanız tekrar mı oynatacak, başka klibe mi blend edecek bilmez. Bu boşluk bilinçlidir: aynı asset viewer'da bir kez, oyunda loop, editörde scrub edilebilir.

Katman ayrımı
Katman Sorumluluk
glTF animations Örnekler, hedefler, interpolasyon tipi
Loader Clip / track nesnelerine çevirme
AnimationMixer Zaman ilerletme, ağırlık, geçiş
Render loop delta ile update

Bu yüzden «GLB'de animasyon bozuk» teşhisinde önce accessor/channel tutarlılığına, sonra mixer kurulumuna bakın. İkinci adım AnimationMixer sayfasındadır. Holodepth kuralı: dosya sözleşmesi yeşil değilse mixer'a dokunmayın; mixer yeşil değilse render loop'a dokunmayın.

Loader çevirisi (sınır)

GLTFLoader clip'leri motor nesnelerine map eder: isimler, süre, track listesi. Bu çeviri «formatı değiştirmez»; yalnızca okunabilir hale getirir. Loader'ın ürettiği clip süresi ile input max uyuşmuyorsa, sorun çoğu zaman CUBICSPLINE düzeni veya eksik kanal değil, zaman birimi / trim politikasıdır. Derin track API'si Three.js dalındadır; burada yalnızca «çeviri katmanı vardır» notu yeter.

Çoklu clip ve isimlendirme

Karakter paketlerinde onlarca clip yaygındır. name alanı isteğe bağlıdır ama runtime seçimi için kritik pratiktir: isimsiz clip'ler indeksle seçilir; export sırası değişince kırılır. Holodepth: clip adını DCC'de bilinçli yazın; indekse güvenmeyin (Material Slots'taki indeks kaydırma tuzağının animasyon yüzü).

  • Aynı node, farklı clip: Walk ve Idle aynı kemikleri hedefler; aynı anda çalmak mixer politikasıdır
  • Farklı süreler: her clip kendi zaman 0…T aralığına sahiptir
  • Paylaşılan accessor: nadiren iki sampler aynı output'u paylaşır; dikkatli olun, yan etki yaratır

Paketleme stratejileri

Üretimde üç yaygın paket görülür: (1) tek GLB, tüm clip'ler içinde; (2) mesh + skin bir GLB, clip'ler ayrı GLB/glTF; (3) clip başına dosya. Format üçünü de destekler; ürün CDN bütçesi ve önbellek politikası seçer. Holodepth: «ilk boyamada Idle yeter, Attack sonra» ise clip ayırma anlamlıdır; her şey tek istekte lazımsa birleşik paket daha ucuzdur. Bu karar keyframe mantığını değiştirmez, dağıtım katmanını değiştirir.

Export: bake, constraint, kayıp

DCC constraint'leri, IK zincirleri, procedural motion glTF'e çoğu zaman bake edilmiş keyframe olarak düşer. Dosyada «IK handle» yoktur; yalnızca sonuç TRS örnekleri vardır. Bu yüzden:

  • Yeniden düzenlenebilir rig web'de yoktur (core)
  • Bake aralığı / örnek hızı dosya boyutunu belirler
  • Constraint bozulması export'ta «keyframe gürültüsü» olarak görünür
Bake yoğunluğu ticareti
Seçim Kazanç Bedel
Seyrek key + LINEAR Küçük dosya Keskin dönüşlerde köşe
Dense bake (ör. 60 Hz) Yüksek sadakat Büyük binary, bellek
CUBICSPLINE Az örnekle yumuşaklık 3× output, karmaşık debug

FBX karakter pipeline'sı ile karşılaştırma FBX dalındadır; burada yalnızca glTF'nin «sonuç odaklı örnekleme» doğası sabitlenir. Bake sonrası DCC'de düzeltilen motion, web'de yeniden constraint ile «düzeltilmez»; yeniden export gerekir.

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

Standart anlatım «animations samplers channels» listesiyle biter. Aşağıdakiler üretimde sık, az yerde derin işlenir.

«Mesh animate olmuyor»

Node translation animate olur; skinned mesh köşeleri skinning ile hareket eder. Morph yoksa, skin yoksa, yalnızca root node kayıyorsa «karakter yürümüyor» sanılır. Keyframe vardır; deform katmanı yoktur. Teşhis: clip var mı, channel hedefi hangi node, skin var mı?

Zaman birimi tuzağı

Bazı araçlar milisaniye veya frame index export eder; glTF saniye bekler. 60× hızlı veya yavaş clip semptomu çoğu zaman birim hatasıdır, mixer değil. Input max'ı 1.2 iken «1.2 dakika» sanmak da ters yönde aynı tuzağıdır.

Negatif scale ve animasyon

Aynalanmış asset'lerde scale.x = −1 sabitse rotation keyframe'leri «ters» hissedilir. Format geçerli olabilir; sanat/pipeline karışımıdır. Transform sayfasıyla birlikte okuyun.

Yetim clip

Hiçbir channel'ı olmayan veya tüm hedefleri sahnede olmayan clip, dosyada yer kaplar ama görünmez. Validator her zaman uyarmayabilir; envanterde channel.target.node geçerliliğini sayın (Channels sayfası).

Bellek = örnek × kanal × bileşen

100 kemik × 3 TRS kanal × 300 key × float ≈ hızlıca megabyte'lar. Draco geometriyi küçültür; animasyon keyframe'lerini sıkıştırmaz (ayrı uzantılar / pipeline gerekir). «GLB hâlâ büyük» teşhisinde animations binary payını ayrı ölçün.

İsim kararlılığı

Runtime clips.find(c => c.name === "Walk") pattern'i format name alanına bağlıdır. Export «Walk.001» üretirsa kod kırılır. Keyframe içeriği doğru olsa da isim sözleşmesi ürün kodunun parçasıdır.

Rest pose ile clip çatışması

Node'un statik TRS'i (rest) ile clip'in ilk keyframe'i farklıysa, oynatma başlamadan önce «bir kare sıçrama» görülür. Bazı loader'lar ilk frame'i uygular; bazıları mixer start'ına kadar rest bırakır. Holodepth: export'ta rest = idle t0 hizası hedefleyin; aksi halde runtime'da bir karelik «snap» politikası yazmanız gerekir.

Kısmi kanal seti

Bir clip yalnızca rotation kanalları taşıyıp translation'ı sabitte bırakabilir. Bu geçerli ve istenen bir seyreltmedir. «Eksik kanal = bozuk dosya» varsayımı yanlıştır; eksiklik bilinçli olabilir. Teşhis: hangi path'lerin gerçekten animate edildiğini channel envanterinden okuyun.

Beş soruluk dosya teşhisi

Keyframe katmanı kontrol listesi
Soru Yeşil ise Kırmızı ise bak
animations.length > 0? Clip var Export / yanlış dosya
Input monoton artıyor mu? Zaman geçerli Bake / birim hatası
Input/output count uyumlu mu? Hiza tamam Accessor bozulması
Zaman birimi saniye mi? Süre makul ms / frame index
Hedef node TRS mi? Animate edilebilir Matrix-only / yanlış node

Holodepth içgörüsü

Animasyon debug'unda önce mixer'a değil örnek sözleşmesine bakın: clip var mı, input monoton mu, input/output count uyumlu mu, zaman birimi saniye mi, hedef node TRS mi? Bu beş soru «oynamıyor / uçuyor / çok hızlı» vakalarının çoğunu dosya aşamasında sınıflandırır.

Keyframe'den sonra

Örneklerin ne olduğu netleşince sıradaki soru bağdır:

  1. Channels & Samplers path, interpolation, target.node
  2. Skinning joints, inverseBindMatrices, vertex weights
  3. Morph Targets shape keys / weights kanalları
  4. Runtime AnimationMixer

Format okuyucusu özeti: animations = clip'ler; keyframe = zaman–değer hizası; çalma = runtime. Partisyon notaları yazar, orkestra sonra gelir.