# VRM to Spritesheet
- https://www.youtube.com/watch?v=z_oDpQ4vzNA
- https://hackmd.io/@XR/avatarlod#Webaverse-Pipeline
Sprites can help with optimization, like generating imposters that improve concurrent user count with assets that look like the original custom avatar.
![image](https://hackmd.io/_uploads/r16YVtMja.png)
## Character Studio Pipeline
- https://github.com/m3-org/CharacterStudio
using character studio to generate the sprites, example animation / manifest file
![joy2](https://hackmd.io/_uploads/S1yM4Kzia.gif)
![image](https://hackmd.io/_uploads/HJqMEtzsp.png)
![walk](https://hackmd.io/_uploads/BybivYGj6.gif)
It works with different sized models as well
![walk2](https://hackmd.io/_uploads/rJH9TKfi6.gif)
---
### r3f-sprite-animator
- https://codesandbox.io/p/sandbox/r3f-sprite-animator-s12ijv?file=%2Fpublic%2Fboy_hash.json%3A1%2C1-204%2C2
```json!
{"frames": {
"Celebration_000":
{
"frame": {"x":1,"y":1,"w":560,"h":440},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":560,"h":440},
"sourceSize": {"w":560,"h":440}
},
"Celebration_001":
{
"frame": {"x":1,"y":443,"w":560,"h":440},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":560,"h":440},
"sourceSize": {"w":560,"h":440}
},
"Celebration_002":
{
"frame": {"x":1,"y":885,"w":560,"h":440},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":560,"h":440},
"sourceSize": {"w":560,"h":440}
},
"Celebration_003":
{
"frame": {"x":1,"y":1327,"w":560,"h":440},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":560,"h":440},
"sourceSize": {"w":560,"h":440}
},
```
https://twitter.com/antpb/status/1752868882291790262
> The biggest thing we need is a list of standard animations. My current implementation is
> - idle
> - idleBackward
> - walk
> - walkBackward
>
>For jumps you could use the walk animation clamped to a frame where the leg is forward. These are all very old problems though so I’m sure there’s some very standard way that is a one file sheet. The names matter most because the implementations could just not care what the animations do and play on the state associated like walk
---
## Notes
- https://community.khronos.org/t/adding-billboard-sprites-to-gltf/106664
- https://x.com/UX3DGpuSoftware/status/1461706770309689348?s=20
- https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#morph-targets
![image](https://hackmd.io/_uploads/Bkr6LtGjT.png)
```json!
{
"Apple": {
"frame": {"x":292,"y":304,"w":60,"h":61},
"rotated": false,
"trimmed": true,
"spriteSourceSize": {"x":23,"y":29,"w":60,"h":61},
"sourceSize": {"w":90,"h":90},
"pivot": {"x":0.5,"y":0.5}
},
...
}
```
snippet from Eidur in Webgamedev discord
> I'm implementing vanilla three and threlte components and utilities at the same time.
```javascript!
export type SpritesheetFormat = {
frames: [x: number, y: number, w: number, h: number][];
animations: Record<string, [frameId: number, duration: number][]>;
sheetSize: [w: number, h: number];
animationLengths: number[];
};
```
---
## glTF extension notes
rough sketch by lasershark
```json!
{
"extensionsUsed": ["m3_spritesheet_animations"],
"images": [
{
"uri": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
}
],
"extensions": {
"m3_spritesheet_animations": {
"spritesheets": [
{
"image": 0,
"name": "Sprite Animations",
"dimensions": { "width": 1024, "height": 1024, "framesH": 4, "framesV": 4 },
"frameRate": 12,
"animations": [
{ "name": "walking", "startFrame": 0, "endFrame": 3, "loop": true },
{ "name": "jumping", "startFrame": 4, "endFrame": 7, "loop": false }
]
}
]
}
}
}
```