Skip to content

Instantly share code, notes, and snippets.

@RainWarrior
Created November 21, 2015 08:41
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RainWarrior/5cd13821c7b53ae771af to your computer and use it in GitHub Desktop.
Save RainWarrior/5cd13821c7b53ae771af to your computer and use it in GitHub Desktop.
First draft of animation stuffs
// B3D model exports 1 track, "main", time = keyframe index;
// looping/not looping is controlled by some flag somewhere.
// possibly a separate file for the animation too, probably not requited at this stage.
{
"model": "yourmod:chest.b3d",
"clips": {
"closed": [{
"clip": "main",
"time": 0
}],
"open": [{
"clip": "main",
"time": 10
}]
},
"states": ["closed", "open"],
"transitions": {
"open -> closed": {
"type": "lerp",
"time": 1
},
"closed -> open": {
"type": "lerp",
"time": 1
}
}
}
{
"animation": "yourmod:engine",
"clips": {
"idle": [{
"child": "default",
"time": 0
}],
"working": [{
"child": "moving",
"time": {
"rate": {
"type": "control",
"name": "speed"
},
"length": 4
"count": "infinity"
}
}]
},
"states": ["idle", "working"],
"transitions": {
"idle -> working": {
"type": "instant"
},
"working -> idle": {
"type": "instant"
}
}
}
// animation specification for vanilla json block models
// weights map to cube corners
{
"model": "yourmod:engine",
"joints": [{
"name": "ring",
"weights": {
"1": [1, 1, 1, 1, 1, 1, 1, 1],
"2": [0, 0, 1, 1, 0, 0, 1, 1]
}
}],
"clips": [{
"name": "default",
"tracks": []
},
{
"name": "moving",
"tracks": [{
"joint": "ring",
"parameter": "y",
"type": "uniform",
"interpolation": "linear",
"samples": [0, 2, 4, 2]
}],
"loop": true
},
{
"name": "moving2",
"tracks": [{
"joint": "ring",
"parameter": "y",
"type": "samples",
"interpolation": "linear",
"times": [0, 0.25, 0.5, 0.75],
"samples": [0, 2, 4, 2]
}],
"loop": true
}]
}
// clips are function from time to the pose
// pose is essentially IModelState
// IModelState output = clip.apply(time)
// Animation state machine calls currentState.apply(world_time)
// users can call animation.switchState("newState") to initiate state transition
// look at the example state machines in afsm folder
// clips
// time transformation
<clip(t)> := {
"child": "<child_name>",
"time": <parameter(t)>
}
// linear blend between 2 clips, time passed through to child clips; progress output is clamped to (0, 1)
<clip(t)> := {
"type": "lerp",
"from": "<child_name>",
"to": "<child_name>",
"progress": <parameter(t)>
}
// parameters: functions from float input to float output
// constant value
<parameter(a)> := <constant>
// basic clip time transformations
// the input time is transformed like this:
// if n == 1:
// output = clamp(rate * (input - start), 0, length)
// in n == N:
// output = clamp(rate * (input - start), 0, N * length) % N
// if n == infinity:
// output = rate * (input - start) % length
<parameter(a)> := {
"rate": <parameter(1)>, // playback rate
"count": <parameter(1)>, // number of repetitions
"length": <parameter(1)>, // length of one repetition
"start": <parameter(0)> // time to start the playback at
}
// linear transform of the input
// output = weight * input + offset
<parameter(a)> := {
"type": "linear",
"weight": <constant>,
"offset": <constant>
}
// simple bezier transform, 0-1 -> 0-1, clamps everything outside
// u = clamp(input, 0, 1)
// v = 1 - u
// output = 3 * v^2 * u * t_start + 3 * v * u^2 * t_end + u^3
<parameter(a)> := {
"type": "bezier",
"t_start": <constant>,
"t_end": <constant>
}
// user-supplied function from float input to float output;
// bind at runtime via animation.addControl("<control_name>", Function<Float, Float>) or smth like that
// name is unique per state machine; multiple parameters in the machine can have the same name - will use the same computed value.
// output = user_call(input)
<parameter(a)> := {
"type": "control",
"name": "<control_name>"
}
<constant> - floating-point number
// vanilla json model, no modifications
{
"elements": [
{
"from": [ 0, 0, 0 ],
"to": [ 16, 4, 16 ],
"faces": {
"down": { "uv": [ 0, 0, 16, 16 ], "texture":"#base" },
"up": { "uv": [ 0, 0, 16, 16 ], "texture":"#base" },
"north": { "uv": [ 0, 0, 16, 4 ], "texture":"#front" },
"south": { "uv": [ 0, 0, 16, 4 ], "texture":"#front" },
"west": { "uv": [ 0, 0, 16, 4 ], "texture":"#front" },
"east": { "uv": [ 0, 0, 16, 4 ], "texture":"#front" }
}
},
{
"from": [ 0, 4, 0 ],
"to": [ 16, 8, 16 ],
"faces": {
"down": { "uv": [ 0, 0, 16, 16 ], "texture":"#base" },
"up": { "uv": [ 0, 0, 16, 16 ], "texture":"#base" },
"north": { "uv": [ 0, 4, 16, 8 ], "texture":"#front" },
"south": { "uv": [ 0, 4, 16, 8 ], "texture":"#front" },
"west": { "uv": [ 0, 4, 16, 8 ], "texture":"#front" },
"east": { "uv": [ 0, 4, 16, 8 ], "texture":"#front" }
}
},
{
"from": [ 4, 4, 4 ],
"to": [8, 4, 8 ],
"faces": {
"north": { "uv": [ 4, 0, 12, "progress" ], "texture":"#chamber" },
"south": { "uv": [ 4, 0, 12, "progress" ], "texture":"#chamber" },
"west": { "uv": [ 4, 0, 12, "progress" ], "texture":"#chamber" },
"east": { "uv": [ 4, 0, 12, "progress" ], "texture":"#chamber" }
}
},
{
"from": [ 4, 4, 4 ],
"to": [ 12, 16, 12 ],
"faces": {
"down": { "uv": [ 0, 0, 8, 8 ], "texture":"#trunk" },
"up": { "uv": [ 0, 0, 8, 8 ], "texture":"#trunk" },
"north": { "uv": [ 8, 4, 16, 12 ], "texture":"#trunk" },
"south": { "uv": [ 8, 4, 16, 12 ], "texture":"#trunk" },
"west": { "uv": [ 8, 4, 16, 12 ], "texture":"#trunk" },
"east": { "uv": [ 8, 4, 16, 12 ], "texture":"#trunk" }
}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment