Json 3D Format

The .jd file format is designed to store geometry and animations in an open standard human-readable format and we can dynamically load it in a multitude of different game engines or frameworks while doesn't force developers to have to redesign the runtime format and implement the converter / exporter for each of them. Each jd file component is designed to be as lightweight as possible for minimize the processing and rendering demands in Direct3D or WebGL / OpenGL / Vulkan frameworks. Using json format is practical because it is much more compact than XML so will take less time to download.

Once your model is exported by the Json Exporter, you can edit the .jd file in any text editor of your choice. A .jd file consists of the following parts:

meta

Meta data for the jd file.

   "meta":
   {
      "version": 1.1,
      "generator": "cgdev json exporter"
   }
         
materials

The materials array is a collection of json material objects. Each material object contains information about colors and texture maps

   "materials":
   [
      {
         "name": "mat1",
         "diffuse": [1,1,1],
         "specular": [0.04,0.04,0.04],
         "glossiness": 30,
         "opacity": 1,
         "maps":
         [
            {
               "name": "Map0",
               "type": "diffuse",
               "uvsIndex": 0,
               "file": "crate.jpg"
            },
            {
               "name": "Map1",
               "type": "bump",
               "uvsIndex": 0,
               "file": "normals.png"
            }
         ]
      }
   ]
       
model

The model object contains a mesh array which can be the largest of all the components. It is optimized geometry data meant to be passed into buffers directly. The groups array are the subsets of a mesh. Each group contains faces in a mesh which using the same material.

   "model":
   {
      "meshes":
      [
         {
             "meta":
             {
                "vertNum": 8,
                "faceNum": 12
             },
             "name": "Box1",
             "node": 1,
             "verts": [-50,0,25,50,0,25,-50,0,-25, ...],
             "vertElement":
             {
                "vertIndices": [0,2,3, ...],
                "normals": [0,-1,0,0,-1,0, ...],
                "uvs": [[1,0,1,1, ...]]
             },
             "face":
             {
                "vertElementIndices": [0,1,2, ...],
                "groups":
                [
                  {
                     "start": 0,
                     "count": 36,
                     "materialIndex": 0
                  }
                ]
             },
             "skin":
             {
                "maxLinksPerVertex": 4,
                "skinBones": [[2],[5,4,3,2], ...],
                "skinWeights": [[1],[0.4455,0.4455,0.099,0.01], ...]
             }
         }
      ]
   }
         
hierarchy

The hierarchy object contains a nodes array. Each node has name, parent and local transformation (position, quaternion, scale). The sceen root has parent index -1. A node also represents a bone if the model has skinned mesh.

    "hierarchy":
    {
        "nodes":
        [
            {
                "name": "SceneRoot",
                "parent": -1,
                "pos": [0,0,0],
                "scl": [1,1,1],
                "rot": [0,0,0,1]
            },
            {
                "name": "Box1",
                "parent": 0,
                "parent_name": "SceneRoot",
                "pos": [0,0,0],
                "scl": [1,1,1],
                "rot": [0,0,0,1]
            },
            {
                "name": "BoneRoot",
                "parent": 0,
                "parent_name": "SceneRoot",
                "pos": [-27.1669,4.38007,0.135981],
                "scl": [1,1,1],
                "rot": [0,0,0,1]
            },
            {
                "name": "Bone1",
                "parent": 2,
                "parent_name": "BoneRoot",
                "pos": [3.35538,-0.226549,-0.135981],
                "scl": [0.479566,1.00044,1],
                "rot": [0,0,0.0581195,0.998308]
            },
            {
                "name": "Bone2",
                "parent": 2,
                "parent_name": "BoneRoot",
                "pos": [3.34092,-0.226549,-0.135981],
                "scl": [0.473054,1,1],
                "rot": [0,0,0,1]
            },
            {
                "name": "Bone3",
                "parent": 2,
                "parent_name": "BoneRoot",
                "pos": [3.37057,-0.226549,-0.135981],
                "scl": [0.479497,1.00027,1],
                "rot": [0,0,-0.0457767,0.998951]
            }
        ]
    }
         
animation

The animation object contains multiple animation clips. Each clip may contain several tracks such as pos, rot and scl.

    "animation":
    {
        "keyframeAnimations":
        [
            {
                "name": "Anims_1",
                "timeline": "seconds",
                "fps": 30,
                "length": 0.666667,
                "animNodes":
                [
                    {
                        "nodeIndex": 0,
                        "nodeName": "SceneRoot",
                        "scl":
                        {
                            "times": [0,0.666667],
                            "values": [1,1,1,1,1,1]
                        },
                        "pos":
                        {
                            "times": [0,0.666667],
                            "values": [0,0,0,0,0,0]
                        },
                        "rot":
                        {
                            "times": [0,0.666667],
                            "values": [0,0,0,1,0,0,0,1]
                        }
                    },
                    {
                        "nodeIndex": 2,
                        "nodeName": "BoneRoot",
                        "scl":
                        {
                            "times": [0,0.666667],
                            "values": [1,1,1,1,1,1]
                        },
                        "pos":
                        {
                            "times": [0,0.666667],
                            "values": [-27.1669,4.38007,0.135981,-27.1669,4.38007,0.135981]
                        },
                        "rot":
                        {
                            "times": [0,0.666667],
                            "values": [0,0,0,1,0,0,0,1]
                        }
                    },
                    {
                        "nodeIndex": 3,
                        "nodeName": "Bone1",
                        "scl":
                        {
                            "times": [0,0.666667],
                            "values": [0.479566,1.00044,1,0.479563,1.00044,1]
                        },
                        "pos":
                        {
                            "times": [0,0.666667],
                            "values": [3.35538,-0.226549,-0.135981,3.35538,-0.226549,-0.135981]
                        },
                        "rot":
                        {
                            "times": [0,0.0333333,0.0666667,0.1, ... , 0.666667],
                            "values": [0,0,0.0581195, ...]
                        }
                    },
                    {
                        "nodeIndex": 4,
                        "nodeName": "Bone2",
                        "scl":
                        {
                            "times": [0,0.666667],
                            "values": [0.473054,1,1,0.473054,1,1]
                        },
                        "pos":
                        {
                            "times": [0,0.666667],
                            "values": [3.34092,-0.226549,-0.135981,3.34092,-0.226549,-0.135981]
                        },
                        "rot":
                        {
                            "times": [0,0.666667],
                            "values": [0,0,0,1,0,0,0,1]
                        }
                    },
                    {
                        "nodeIndex": 5,
                        "nodeName": "Bone3",
                        "scl":
                        {
                            "times": [0,0.666667],
                            "values": [0.479497,1.00027,1,0.479498,1.00027,1]
                        },
                        "pos":
                        {
                            "times": [0,0.666667],
                            "values": [3.37057,-0.226549,-0.135981,3.37057,-0.226549,-0.135981]
                        },
                        "rot":
                        {
                            "times": [0,0.0333333,0.0666667,0.1, ..., 0.666667],
                            "values": [0,0,-0.0457767, ... ]
                        }
                    }
                ]
            }
        ]
    }