Building your catalog

Catalogs define what assets your users may use in order to customize their avatars. By default MSquared provides an extensive library of parts to get you started, however you may want to build your own catalog for a custom experience.

Catalogs are hosted json files which the Avatar Editor ingests and presents to the user so they can pick the assets they desire. At it's root a catalog is defined as a set of skin and bodyTypes configurations. How to setup each section is outlined below.

{
    skin: Skin;
    bodyTypes: BodyTypes;
}

Skin

By default the Avatar Creator supports 7 skin tones. If you need more skin tones please reach out to the MSquared Team. Any parts which are skin dependent will require a variation to be created for each skin color.

{
    name: string;
    index: number;
}

For most projects the following skin setup can be used:

"skin": [
    {
       "name": "01",
        "index": 1
    },
    {
       "name": "02",
        "index": 2
    },
    {
       "name": "03",
        "index": 3
    },
    {
       "name": "04",
        "index": 4
    },
    {
       "name": "05",
        "index": 5
    },
    {
       "name": "06",
        "index": 6
    },
    {
       "name": "07",
        "index": 7
    }
],
    

Body Types

By default the Avatar Creator supports 2 body types, (bodyA and bodyB). If you need more body types please reach out to the MSquared Team. Every catalog should define parts for both bodyA and bodyB.

A body type is composed of body, head, hair, top, bottom, and shoes - each containing a list of parts.

  body:{
    torsoArms: string; 
    arms: string;
    legsFeet: string;
    legs: string;
  };
  head: {
    list: HeadPart[];
  };
  hair: {
    list: HairPart[]
  };
  top: {
    list: TopPart[]
  };
  bottom: {
    list: BottomPart[]
  };
  shoes: {
    list: ShoesPart[]
  };

Defining a body

The base body parts must be provided, which the user's chosen assets will be placed on top of. All fields which make up the body are skin dependent.

Defining a part

A part is composed of the following fields:

  • file

    • Required for every part

    • References the thumbnail and model by appending .webp and .glb respectively to the provided URI

  • secondary

    • Optionally provided to TopPart and BottomPart

    • Loads an additional glb for the slot

    • File referenced in the same way as the primary file but no thumbnail is required

  • torso

    • Optional field on TopPart

    • If value is true then the torso will be rendered

    • For example, this may be needed for shirts but a hoodie covers the whole torso so by default it will not need to render the torso

  • legs

    • Optional field on BottomPart

    • If value is true then the legs will be rendered

    • For example, this may be needed for shorts but a pair of jeans covers the whole legs so by default it will not need to render the legs

Additionally the head slot is skin dependent.

Example Catalog

This minimal example only has one body type configured, selecting the other body type in editor with this will cause an error

{
  "skin": [
    {
      "name": "01",
      "index": 1
    },
    {
      "name": "02",
      "index": 2
    }
  ],
  "bodyTypes": {
    "bodyA": { ...omitted... },
    "bodyB": {
      "body": {
        "torsoArms": "https://storage.googleapis.com/glb-content-bucket/parts/Body_B_BodyTorsoHeadless",
        "arms": "https://storage.googleapis.com/glb-content-bucket/parts/Body_B_BodyArmsHeadless",
        "legsFeet": "https://storage.googleapis.com/glb-content-bucket/parts/Body_B_BodyLegsFeet",
        "legs": "https://storage.googleapis.com/glb-content-bucket/parts/Body_B_BodyLegs"
      },
      "head": {
        "list": [
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Head_B_Mixed_B"
          },
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Head_B_Mixed_A"
          }
        ]
      },
      "hair": {
        "list": [
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Hair_B_NatalieHair_Brown_01"
          },
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Hair_B_NatalieHair_Extra_01"
          }
        ]
      },
      "top": {
        "list": [
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Top_B_Hoodie_WindbreakerBlackWhite_01"
          },
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Top_B_RockJacket_VinylWhite_01",
            "secondary": "https://storage.googleapis.com/glb-content-bucket/parts/Top_B_RockTopLong_White_01",
            "torso": true
          },
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Top_B_FlannelShirt_CheckerdRed_01",
            "secondary": "https://storage.googleapis.com/glb-content-bucket/parts/Top_B_BaseballJersey_BlackRed_01"
          }
        ]
      },
      "bottom": {
        "list": [
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Bottom_B_TightJoggers_TanJeans_01"
          },
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Bottom_B_PleatedSkirt_TweedWhite_01",
            "secondary": "https://storage.googleapis.com/glb-content-bucket/parts/Bottom_B_StockingsGarterRibbon_White_01",
            "legs": true
          }
        ]
      },
      "shoes": {
        "list": [
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Shoes_B_HighTops_WhitePink_01"
          },
          {
            "file": "https://storage.googleapis.com/glb-content-bucket/parts/Shoes_B_HighTops_RunningBlue_01"
          }
        ]
      }
    }
  }
}

Asset Files

Assets, including the thumbnail and model, should be hosted using a high-availability, high-throughput CDN to avoid bottlenecks. Additionally, configure your CDN with aggressive caching to minimize network requests and speed up downloads. The files must be publicly downloadable.

Files referenced in the below catalog do not have a file extension included. This is so they can reference both the thumbnail and model by simply appending .webp and .glb respectively.

A common issue ran into when configuring asset files is the bucket hosting the assets does not have the correct CORs configuration leading to the Avatar Creator UI not being able to fetch the content. Please ensure whatever bucket is used for hosting content allows cross origin requests.

Skin Dependent Parts

Additionally, some parts are marked as skin dependent. These will have the skin index, (preceded by an underscore), appended before the extension so specific parts can be set based off of the skin color

Example files

Given the base file reference:

example.com/my-storage/body-part

It would be expected that it would be possible to publicly access both

example.com/my-storage/body-part.webp // The thumbnail.
example.com/my-storage/body-part.glb  // The model.

Furthermore if the part was skin dependent the following should be accessible:

example.com/my-storage/body-part_01.webp // The thumbnail for skin tone 01.
example.com/my-storage/body-part_01.glb  // The model for skin tone 01.
example.com/my-storage/body-part_02.webp // The thumbnail for skin tone 02.
example.com/my-storage/body-part_02.glb  // The model for skin tone 02.
...
example.com/my-storage/body-part_07.webp // The thumbnail for skin tone 07.
example.com/my-storage/body-part_07.glb  // The model for skin tone 07.

Last updated

Was this helpful?