The goals are:
- directly usable in Javascript using
JSON.parse()
- same node types and properties as VRML / X3D
- don't use strings for boolean or numbers
- write nodes always the same way, regardless of the container
- avoid deep nesting
- avoid duplicated data
Two shapes:
[
{
"$": "Shape",
"appearance": {
"$": "Appearance",
"material": {
"$": "Material",
"diffuseColor": [0.8, 0.8, 1]
}
},
"geometry": {
"$": "Box",
"size": [2, 2, 2]
}
},
{
"$": "Shape",
"appearance": {
"$": "Appearance",
"material": {
"$": "Material",
"transparency": 0.5
}
},
"geometry": {
"$": "Sphere",
"radius": 5
}
}
]
Re-using a node (DEF/USE):
[
{
"$DEF": "myshape",
"$": "Shape",
"appearance": {
"$": "Appearance",
"material": {
"$": "Material",
"diffuseColor": [0.8, 0.8, 1]
}
},
"geometry": {
"$": "Box",
"size": [2, 2, 2]
}
},
{
"$": "Transform",
"translation": [1, 0, 0],
"children": [
{
"$USE": "myshape"
}
]
}
]
Transforms in a Group:
[
{
"$": "Group",
"children": [
{
"$": "Transform",
"translation": [-2, 0, 0],
"children": [
{
"$": "Shape",
"appearance": {
"material": {
"$": "Material",
"diffuseColor": [0, 1, 0.5]
}
},
"geometry": {
"$": "Box"
}
},
]
},
{
"$": "Transform",
"translation": [2, 0, 0],
"children": [
{
"$": "Shape",
"appearance": {
"material": {
"$": "Material",
"diffuseColor": [0, 0.5, 1]
}
},
"geometry": {
"$": "Sphere"
}
},
]
}
]
}
]
$ because each object is represented by the same set of fields regardless of it's position in the tree, and MFNode that contain multiple types of node don't lose the order of the nodes.
Don't repeat properties: most JSON parsers discard or refuse duplicated properties.
$ because it produces less deep structures.
Array because it allows MFNode of multiple types of nodes, not just one type. Also it's more explicit when a type has multiple MFNode properties.
[1,2,3,4,5,6] because it's like VRML & X3D, less deeply nested, and easier for WebGL Typed Arrays.
Explicit because it avoids guessing, doesn't break the "always write a node the same way" rule, has shorter paths to access nested values and uses the same paths as VRMLscript.
Use
$ ROUTE
objects for expressing routes.
Like VRML, use simple String values for SFString values that the XML encoding expresses as CDATA.
Use Metadata nodes when comments must be part of the scenegraph, or regular Javascript-style comments with a JSON5 parser.
You can use non-standard $
types to make custom nodes.
{
"$": "Teapot",
"bottom": false,
"size": 5
}
The implementation would depend on the 3D engine, however I'd advise against putting the JS code inside the scenegraph itself because it would run with eval(), which is not recommended.
Better structure your code using modules (CommonJS, ADM or ES6 classes) that generate JSON on demand, or even Web Components like A-Frame.