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.
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, ... ]
}
}
]
}
]
}