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