콘텐츠로 이동

파일 포맷

두 OTS 파일 모두 들여쓰기가 되어 있고 읽을 수 있는 순수 UTF-8 JSON입니다. 텍스트 에디터로 열어보거나, 버전 관리에서 둘을 diff하거나, 하나를 읽는 스크립트를 짤 수 있습니다. 이건 의도적입니다 — 들여다볼 수 없는 교환 포맷은 디버깅할 수 없는 교환 포맷입니다.

현재 포맷은 버전 4입니다.

공통 헤더

두 포맷은 똑같은 방식으로 시작합니다:

{
  "format": "octo_anm",
  "version": 4,
  "source": "harmony",
  "fps": 24.0,
  "coordinate_system": {
    "up": "y",
    "hand": "right",
    "unit": "meters",
    "rot_order": "xyz",
    "rot_repr_anim": "euler_deg",
    "rot_repr_rest": "quat_wxyz"
  }
}
의미
format octo_pvt 또는 octo_anm
version 포맷 버전. 정확히 일치해야 합니다 — 아래 참조
source 어떤 애플리케이션이 썼는지: harmony, blender, 또는 maya
fps 소스 씬의 프레임 레이트
coordinate_system 값들이 놓인 공간 — 좌표계 참조

하위 버전 마이그레이션 없음

reader는 오직 자기 버전만 받아들입니다. v3 파일을 v4 빌드에 로드하면 이렇게 보고합니다:

unsupported version 3 (this build writes/reads v4; no backward migration — re-export from the source DCC)

이건 실수가 아니라 선택입니다. 오래된 파일을 조용히 마이그레이션한다는 건 그 숫자들이 무슨 뜻이었는지 추측한다는 뜻이고, 추측이 틀리면 대놓고 망가진 rig이 아니라 미묘하게 어긋난 rig이 나옵니다. 소스에서 다시 export하는 건 몇 초면 되고 항상 정확합니다.


.pvt — pivot 파일

{
  "format": "octo_pvt",
  "version": 4,
  "source": "harmony",
  "name": "spaceship",
  "scale_factor": 1.0,
  "pivot_space": "local",
  "fps": 24.0,
  "coordinate_system": { "…": "…" },
  "bones": [
    {
      "name": "hip",
      "parent": null,
      "pivot": [0.0, 0.0, 0.0],
      "rotation": [1.0, 0.0, 0.0, 0.0],
      "path": "Armature/hip",
      "rig": "spaceship",
      "is_camera": false
    }
  ],
  "cameras": []
}
의미
name rig의 이름
scale_factor 사용자용 Scale 옵션. pivot은 쓸 때 이 값을 곱하고, 읽을 때 나눕니다
pivot_space local (parent 기준) 또는 armature
bones[].pivot rest 위치
bones[].rotation rest 회전, quaternion [w, x, y, z]
bones[].path 소스 씬에서의 항목 전체 경로 — 매칭에 쓰이고, 서로 다른 rig에 있는 동명 항목을 구분하는 데도 쓰입니다
bones[].rig rig 태그

path, rig, is_camera는 비어 있으면 생략되므로, 단순한 파일은 작게 유지됩니다.


.anm — 애니메이션 파일

{
  "format": "octo_anm",
  "version": 4,
  "source": "maya",
  "frame_range": [1, 60],
  "fps": 24.0,
  "coordinate_system": { "…": "…" },
  "pegs": [
    {
      "name": "hip-P",
      "path": "Top/spaceship/hip-P",
      "parent": "root",
      "rest_pivot": [0.0, 0.0, 0.0],
      "rest_rotation": [1.0, 0.0, 0.0, 0.0],
      "rig": "spaceship",
      "is_camera": false,
      "source_modes": {
        "position": "separate",
        "rotation": "euler",
        "scale": "separate",
        "enable_3d": true
      },
      "keyframes": [
        {
          "frame": 1,
          "pos": [0.0, 0.0, 0.0],
          "rot": [0.0, 0.0, 0.0],
          "rot_quat": [1.0, 0.0, 0.0, 0.0],
          "scl": [1.0, 1.0, 1.0],
          "interp": "BEZIER",
          "handles": { "pos": [], "rot": [], "scl": [] }
        }
      ]
    }
  ],
  "cameras": []
}

자급자족 필드

parent, rest_pivot, rest_rotation, rig은 각 peg 안에 접혀 들어간 .pvt 내용입니다. Create Rig.anm 하나만으로 동작하는 스켈레톤을 세울 수 있는 이유가 바로 이것입니다. 애니메이션 파일 (.anm)를 참조하세요.

Keyframe

의미
frame 프레임 번호
pos 위치, 정규 공간의 미터
rot Euler XYZ, 도(degree) — 사람이 읽을 수 있는 형태
rot_quat 같은 회전을 quaternion [w, x, y, z]으로 표현한 것. world matrix bake에서 나옵니다
scl 스케일
interp BEZIER, LINEAR, 또는 CONSTANT
handles 절대 bezier handle. 축별로, 채널별로 묶여 있습니다

rot_quat이 이깁니다

둘 다 있을 때는 rot_quat이 권위 있는 값이며 모든 importer가 그쪽을 선호합니다. 순서 독립적이라서 Euler 순서 모호성을 통째로 피해 갑니다. rot은 읽기 쉬운 대비책으로 남겨둡니다.

Maya와 Blender의 bake는 rot_quat과 나란히 handle을 내보내지 않습니다. 로컬 프레임 기준 handle은 bake된 world 커브에 대응되지 않기 때문입니다. 보간 타입 자체는 그대로 전달됩니다.

Handle은 (프레임, 값) 공간에서의 절대 [[left_x, left_y], [right_x, right_y]] 쌍이며 — 축마다 하나씩, pos, rot, scl로 묶입니다. 상대값이 아니라 절대값이라서, 들여올 때 프레임 레이트에 맞춰 다시 유도할 필요가 없습니다.

source_modes

peg이 소스 애플리케이션에서 어떻게 제작되었는지에 대한 기록 — 위치가 separate인지 path 기반인지, 회전이 Euler인지 quaternion-path인지, 3D가 켜져 있었는지.

힌트일 뿐, 그 이상은 아닙니다

source_modes어떤 값에도 영향을 주지 않습니다. 파일을 읽는 사람을 위한 진단 정보입니다. importer가 이것 때문에 커브를 쓰는 방식을 바꾸지는 않습니다.


카메라

두 포맷 모두 같은 카메라 블록을 담으며, 이름으로 애니메이션 항목과 연결됩니다:

의미
name, peg, path 신원, 그리고 어떤 항목이 이 카메라를 움직이는지
is_default 이것이 씬의 기본 카메라인지 여부
fov, fov_axis 시야각 — Harmony의 관례에 맞춘 수직
override_fov Harmony의 카메라별 FOV 오버라이드 플래그
near_plane, far_plane clip plane, 정규 공간의 거리
near_field, far_field Harmony의 원래 clip 값을 field 단위로. Harmony 왕복이 무손실이 되도록 보존합니다
angle roll, Z축 기준 도(degree)
offset_x/y/z, pivot_x/y peg 기준 배치
rig rig 태그

Cameras를 참조하세요.


실무 메모

파일은 작습니다. 60프레임 샷이 담긴 완전한 캐릭터 rig도 수백 킬로바이트 수준입니다. 이메일로 보내거나, 버전 관리에 넣거나, 기록용으로 샷 옆에 함께 두어도 괜찮습니다.

diff가 됩니다. 같은 rig을 두 번 export하면 비교 가능한 JSON이 나오므로, "이 두 버전 사이에 뭐가 바뀌었나"가 추측이 아니라 텍스트 diff가 됩니다.

이름은 여러분 마음대로. OTS는 파일 이름을 신경 쓰지 않습니다. 파일을 식별하는 건 그 안의 format 키입니다. .pvt / .anm 확장자를 유지하는 건 단지 파일 선택 창이 제대로 동작하게 하기 위해서입니다.