Appendix A (object reference)
From Wiki
This page is a complete (work in progress) object reference for the JSOM (JSON Sword-of-Moonlight Object Model) schema. Anyone who wants to can participate in the drafting of this specification or whatever you might call it. It is open to whoever likes what they see / would like a little more. You can call it the JSON Scene Object Model if that makes you more comfortable. If the name is not already taken by some more respectable effort that is.
Contents
- 1 Overview
- 2 Forbidden properties
- 3 Universal properties
- 4 Namespace properties
A sample JSOM/JSON file formatted for readability:
{ "externals": [ { "json": "big_hairy_data_file.json.gz" }, { "png": "my_super_duper_texture.png" } ], "arrays": [ { "url": 0 } ], "images": [ { "url": 1, "alpha": false, "width": 256, "height": 256 } ], "attributes": [ { "array": 0, "semantic": "position", "stride": 8 }, { "array": 0, "semantic": "normal", "stride": 8, "start": 3 }, { "array": 0, "semantic": "texcoord0", "size": 2, "stride": 8, "start": 6 } ], "elements": [ { "mode": "TRIANGLES", "array": 1, "start": 0, "count": 2388 } ], "semantics": [ { "position": { "glsl": "vec4(mix(position,tweenpos,tween),1)" }, "state0(X)": { "glsl": "X" } } ], "materials": [ { "semantics": [0,null], "texture": [0] } ], "graphics": [ { "clearance": [ [-0.481000,0.481000], [-0.000000,1.824000], [-0.672000,0.341000] ], "graphics": [ { "pass": 0, "sides": [0,null], "primitives": [0], "keygroups": [0] } ] } ], "keyframes": [ { "url": 0 } ], "keygroups": [ { "url": 0 } ], "tracks": [ { "key": [1], "title": "Animation ID #0" }, { "key": [2], "title": "Animation ID #4" } ] }
Overview[edit]
More than anything else the "JSOM" schema is a creature of the popular JSON information exchange format. It is a JSON schema after all. JSON is a subset of the popular JavaScript programming language / ECMAScript standard. Minimalism is part and parcel of the JSON specification, which is another way of saying it is really very brief. Now is a good time to read about JSON if you've never heard of it before. Any code in this document is JSON. It's pretty simple stuff, so JSOM by extension is pretty simple. That's good and bad. In case you are wondering why things are so simple, well that is why. OK! Moving on.
The job of a JSOM (JSON) resource is to deliver graphics to an application that is probably programmed in JavaScript and running in a JavaScript engine of some kind, probably in a WWW browser. The application should be to display the graphics themselves, or combine them with other graphics in an interactive fashion if need be. This should be fast to do and not overly complicated. Animation is also very important. In theory every aspect of the JSOM resource should be able to be animated. Animation is not the same as interaction, however direct interaction and scripting is a desirable feature as well.
At the top level of a JSOM resource you will find several named arrays of objects with various characteristic names; externals, templates, images, sounds, arrays, attributes, elements, semantics, materials, graphics, keyframes, keygroups, tracks, are all core to the specification. These are properly referred to as "namespaces" and they represent lists of items. The items themselves can contain sub-lists, so that the general structure of a namespace is more like an outline; Eg. item 0.1.1 refers to the first (zero-based) item at the top of the namespace, and then to the second item of its sub-list, and then to the second item of that item's sub-list. Items can be alternatively addressed by name, hence the term "namespace". Names within a namespace are assumed to be unique IDs, and are not hierarchically arranged, dotted or otherwise. Should a name collision occur, the previous holder of the name is effectively disappeared.
Constants[edit]
Constant values are always "right value" capitalized character strings. For the most part paralleling OpenGL constants, formed by stripping the "GL_" prefix; same as WebGL. The constants do not however have numeric equivalents. Applications are responsible for mapping these constants both to their numeric equivalents and to the native platform if not OpenGL.
Items and Lists[edit]
A JSOM item is a top-level object in the namespace hierarchy. So-named because they are always an object item of a JSON array. Items in an array do not have names, but you can assign a name to an item by giving it a name property. If an item contains a property with the same name of its namespace it will form a sub-list. For examples, an item in the graphics namespace, may contain a 'graphics' property of its own. The graphics property can then contain a list of "sub-graphics" and so on. The only thing to remember is that this kind of "nesting" is strictly limited to the operative namespace. You cannot for instance add a sub-list of "images" to an item in the graphics namespace. Any property that looks like a sub-list from another namespace is more than likely an #index.
Indices, Index singular[edit]
Indices are always properties of items, or part of a multi-index array that is itself a property. Each index refers to an item in one of the aforementioned namespaces, if any item at all. The name of the property pre-determines the namespace the index belongs to. If you don't know for sure, then you just have to look it up. Eg. an index property named 'sound' is going to be made up of indices which refer to the 'sounds' namespace. Pretty straightforward. Sometimes however the name of the property does not correspond letter by letter to the name of the namespace. That is what this reference is for.
Now when indices are part an array, you can rest assured in the knowledge that all of the indices refer to items of just one of the multiple namespaces. And just to make things even simpler, you can always bet that a property is either an array (referring to 0 or more items) or not an array (referring to a single item) but never either or. The general rule is that if it would ever under any circumstance make sense to refer to more than one item by with a particular index property then that property is going to be a multi-index array. And before we are done with index arrays. In case you are wondering. An array may be the JSON null value, and it may be empty, and it may contain all null values, in any of these cases it is functionally equivalent to the index array not existing at all, which is the same as a non existent or null value non-array index property.
Index values come in five interchangeable flavors:
- A null value; a null value, as described by the JSON specification. This is equivalent to the property not being defined in the first place.
- A single numeric value; a number indicating a top-level item of the relevant namespace at resource scope. Indexes cannot refer to a scope above the resource in which they are defined. See #External Resources for details.
- A single JSON character "string" index. This is a non-numeric #name proper index, Ex. "left leg". These are global to a namespace, any string literal works.
- An array of subscripts of the form, [optional joints, optional name, optional numbers]. See #joint, and #name. Each subsequent numeric subscript indicating an item in a sub-list as explained in the #Items and Lists section. So think comma notation rather than dot notation, but an outline nonetheless. Joints take precedence over names.
- An inline item; rather than indexing an item, a new item can alternatively be defined on the spot. Often this is the right idea. The only thing to bear in mind is that inline items can never be indexed into from other indexes. In case you are wondering, yes (in theory anyway) you can make a strictly serial JSOM resource consisting of pure inline notation (it is not difficult to prove that keyframe animation would be out for such a resource, however everything else at the time of this writing is probably feasible; it really boils down to whether mutual indices are required for some feature to do its job).
External Resources[edit]
The content of a JSOM resource can pull in outside JSOM resources through the power of external references. This is great both for organization and not putting all of your eggs into one basket; so to speak. A typical JSOM resource also includes non-JSOM resources: a reference to a PNG image for example; but these types of resources are dead ends as far as the JSOM schema is concerned, so we will not speak of them again.
The inclusion mechanism is one-way, "downstream", which is to say, a resource can include references to sub-resources, but not vice versa. There is a way around this limitation to some degree, namely through the judicious use of #Template Expansion (keep reading) except for that to say templates refer to or include anything would demonstrate a misconception of how the mechanism is supposed to work.
Unidirectional data flow is not a hard constraint. It is open to discussion. The arguments against it is a resource becomes more brittle if it can reference things upstream. An implementation would have to keep track of what is upstream in every context at the function level should the resource be shared. A special mechanism would need to be devised for upstream indexing. In general its comforting to know that your resources are functionally self contained units top to bottom. Conceptually a resource has direct knowledge of what lies below it. And no clue about what may lay above.
What can be a reference? In practice any item may be a reference. A reference to what? A reference to the namespace of another resource that bears the name of its own namespace. In fact the referenced namespace becomes one of those sub-lists we talked about. Except for one thing! A reference is a second-class item. Even though it has an address, it cannot be addressed; by an index for example. There is really no reason to do so. And either way the reference effectively becomes a placeholder for the first item of the included resource (or no item, if no such item exists) due to "lazy" indexing rules. Maybe you've heard of it. Oh you haven't?
Lazy indexing rules follow: whenever a reference is indexed. If an item in its sub-list is not indexed, then the index will indicate the first item included by the reference, or if that item is itself a reference, the first item included by that reference, and so on. This can be referred to as the "underflow" rule--if you want. If the reference is the last item in its list then the remainder of a numeric index is used to index into the reference's sub-list. You can call this the "overflow" rule--if you will. Whether lazy indexing is technically "lazy" is up to debate. Dotted and named indexes may be unnecessary if you can refactor your resources about lazy indexing. You might even leverage such a scheme to shim in an extra layer of modularity to whatever it is you are doing. Just make sure you understand the rules and everyone involved understands when they are in play.
Template Expansion[edit]
A #templates item is a generic bag of properties. In and of itself without meaning. It is not a true item though the same indexing rules apply. Depending on the semantics of an index the properties of the template are usually conferred in some way to some other item either directly or indirectly. Whenever the transfer of properties does take place, it is what we are calling template expansion for our purposes here.
The most basic example of expansion is the universal 'template' property. Every item may have this property: which says that on top of what properties the item has, it will also have the properties of said template(s). Expansion happens at the latest just before the item is to be considered in terms of its properties, first index to last index the template(s) properties are copied into/over those of the item being expanded. Templates may index other templates, same rules apply. Properties are never added together or anything like that. Everything is strictly overwritten. Which in JavaScript normally means that only an object reference or a similarly irreducible literal will be copied. This can be used to your advantage if you need to keep memory overhead to a minimum. Ie. by sharing macro values whenever practical.
JavaScript is usually best at chewing up memory and slow about computing anything on the fly. What seems to work is to compute everything once and keep it in memory if speed is important. So if nothing else effectively managing said memory can be a considerate thing to do on behalf of what users you are able to sucker into whatever it is you are up to.
But that's not the end of templates. Templates are an integral part of the JSOM schema. Template indexes do occur in the wild and you will probably come across one sooner or later. You should just remember that templates do not do anything on their own. Their indexes are inert until expansion happens, and that does not necessarily happen inside the resource in which the template is defined. But what about #expand you ask? Glad that you asked... or ah no. Just kidding. That can be for homework.
Extensibility[edit]
Word of warning. You may come across properties that are not mentioned anywhere in this document. They may just be experimental, or they may be user defined properties; which are not-not permitted. A resource might want to (for instance) attach some custom variables to some programmable shaders. Or it may be that some properties are just purely ancillary to some JSOM aware application layer.
Regardless there has been no consideration as of yet concerning collision of custom properties with properties added by a future version of JSOM or whatever, so you can just go wild if you need to.
Modularity[edit]
See #ref and #External Resources.
Forbidden properties[edit]
These are not properties, but properties which should never be, and why they should never be. Not necessarily the same as reserved properties. This draft of this document is fairly conservative in terms of not reserving anything or even mentioning anything beyond what is bare bone essential JSOM-wise.
length[edit]
A "length" property should never appear. We don't allow this just to be ultra sure that an object is never confused for an array. It's a JavaScript thing. Look into it.
Universal properties[edit]
This section lists properties which are common to all items regardless of namespace. These properties do not take on special meaning under any circumstances.
name[edit]
The name property permits an alternative to numeric indexing, with the downside of needing to have names handy or some mechanism for generating them on the fly. Names should be unique unless the behavior you are looking for is to overriding of a named item by the later/possible inclusion of an item with the same name. A name is a character "string".
joint[edit]
The joint property introduces a named "joint" into the namespace creating a sub-namespace. Items below the joint cannot be indexed by name except by using the array index notation where first the joint, and then any subsequent joints, is specified. With joints you can separate out incompatible namespaces which would otherwise result in definite or potential name collisions. A joint is a character string.
For example, if two items of the graphics namespace represented a couple of people, and each graphic below each person is a body part named, "left arm", "left foot", etc. To avoid name collisions between each of the couple's constituent graphics you would need to define the joint property for each person:
"graphics": [ { "joint":"Andy", "graphics":[...,{"name":"left elbow"},...] }, { "joint":"Buck", "graphics":[...,{"name":"left elbow"},...] } ], "controls": [ { "space":["Andy","left elbow"] } ]
template[edit]
The template property is an array of indexes into the #templates namespace. All properties from the templates indexed will be added, first to last, to the item containing the template property, including any template properties contained within the templates themselves. Note that properties overwrite one another. They are never added together in any way. A template is an array of indices.
ref[edit]
The ref property is a name that refers to an undetermined external resource. The item containing a ref property is a reference according to #External Resources however the resource in question is to be determined by the JSOM client application, which will use the value of ref to determine which resource to use. A ref is a character "string".
url[edit]
The url property is an index into the #externals namespace. It results in a reference item that is determined entirely by the resource (compare to #ref above) at the time of its creation. A url is a singular index.
try[edit]
The try property is an array of indices into the current namespace. It indicates that the first index should be used instead of the current item if possible, and if not possible, the next index, and if all indices are not possible to use, then the item itself should be used as last resort (if possible). The most likely reasons for an item being unavailable are: it was never defined in the first place, it is an external resource which has not finished loading, it is an external resource that has been filtered out by #priority. An application is free to give up on an item for any reason or no reason. A try is an index array.
<namespace>[edit]
Where <namespace> is the same name as the current namespace, Eg. graphics for the graphics names, images for the images namespace. This property is an array of namespace item objects which will form a sub-list beginning at the current item of the current namespace. A <namespace> is an array of namespace item objects.
keygroups (property)[edit]
In theory+ all first class (see #External Resources) items can be animated by #keyframes. Exceptions are #templates and keyframes themselves. In order to participate in a keyframe animation an item must be a member of one or more #keygroups. To indicate its membership in a keygroup the keygroup must be included in this index once and only once. The keygroups property is an array of indices into the keygroups namespace.
More namespaces where animation is impractical and or borderline nonsensical: #tracks, #evaluators, #keygroups, #arrays, #semantics, #scripts, #controls, #externals (see #keyframes and #templates mentioned above).
Namespaces where real-time animation would almost certainly be compromised if animated: #paints.
#Universal properties which ARE open to animation: #url, #ref (the rest are prohibitied).
+Animation applicability and performance is application defined.
Namespace properties[edit]
Each heading of this section is representative of a namespace of the same name. Each section below each heading describes the function of the namespace and the non-extended (see #Extensibility) properties that are meaningful to the items of that namespace.
externals[edit]
Each item of the externals namespace is a typed URL, or combination of redundant and or alternative typed URLs. Without exception "externals" are indexed by the universal #url property.
<typed URLs...>[edit]
Where <typed URLs...> is understood to be any number of property key / value pairs where the value is a URL in character string form, and the key communicates the format of the resource believed to be on the other end of the URL value. For example an external JSOM resources might be announced by a "json" key, while "png" might indicate an image. Multiple such properties can coexist where it is understood that each typed URL pair represent the same resource but in different formats. Which format is ultimately used (if any) is up to the JSOM client application, as is interpretation of the keys and values.
It is not necessary that the type accurately represent the format of the resource indicated by the URL. For instance, a client app may only recognize images by the "png" type regardless of the image format (which may not necessarily be PNG). This is application defined behavior.
priority[edit]
The priority property is a number. A complex resource with many external components can indicate in what order it would prefer each component be processed. The minimal value, and highest priority, is 1. The higher the number the lower the priority. It is not required that applications actually sort externals by priority. Typically the external data will get loaded up asynchronously and usually it is desirable to integrate the resource as soon as possible.
Applications should implement a minimum highest priority threshold, where any external component with an at or higher priority than the desired minimum should be fully loaded before the resource is presented to the end user for the first time. It is also desirable to allow for a maximum lowest desired priority threshold, where any external with a priority lower than the maximum is to be discarded (or ignored) entirely.
templates[edit]
namespace[edit]
The namespace property explicitly states the namespace that the template is intended to be compatible with. Applications may ignore this parameter or perform validation against it if they so choose. If 'null' the template is not limited to any particular namespace, its properties may be expanded into any context whether it makes sense to do so or not.
expand[edit]
The expand property is a character string that modifies expansion behavior. It may be null (see #Template Expansion) or "inline". Inline expansion behavior is to immediately expand all index properties to inline objects. Indexes are taken to be local to the resource defining the template.
It is application defined behavior as to what property names are considered indexes. It may aid the application if the template's #namespace property is defined, it may not. An application is not required to implement inline expansion.
<properties...>[edit]
Where <properties...> is understood to be any number of generic property key/value pairs. For example, if the template is intended to be compatible with the #graphics namespace, it may have an #primitives property. When the primitives property is expanded into a graphic that graphic will then contain a copy (usually by reference) of the templates primitives property.
The entire function of templates is to contain any number of such properties. Universal properties cannot take part in template expansion, and neither do template specific properties (see namespace and expand above.)
images[edit]
Each item of the images namespace is a graphical image which can include additional 3D texture mapping properties. If an image needs to be texture mapped in more than one way it should be represented by multiple items in the images namespace.
The pixel data of the image can be in the form or a #url or an #rgb (see rgb below) property, where a url is an index into the #externals namespace for a typed image url, and an #rgb property describing a 1x1 pixel image. An application may fall back to the rgb value if the url value cannot be resolved.
rgb[edit]
This is a common property describing a red, blue, green, alpha colour. It is a 3 or 4 number array where each number is a colour component (in red, blue, green, alpha order) where red, blue, and green are more than likely in the sRGB gamut, where 0 is pure black and 1 is pure white. Alpha is transparency and defaults to 1 (fully opaque).
See #images for how the rgb property applies to items of the image namespace.
alpha[edit]
The image alpha property is a boolean value, either true or false. If true it is an assertion to the client application that the image contains non opaque (transparent or semi-transparent) pixels. If false it is an assertion that the image is fully opaque.
What an application does with this information is implementation defined. Regardless, if present, alpha should reflect the content of the image faithfully.
width[edit]
The image width property is a numeric value asserting the width of the image in pixels.
What an application does with this information is implementation defined. Regardless, if present, width should reflect the content of the image faithfully.
height[edit]
The height of the image in pixels. Language of #width applies identically.
space[edit]
The image space is an index to another image from which the #state property (next section) is taken to be relative to / multiplied with. The default space for an image is the image "above" it in the namespace in terms of nesting, as opposed to listing. If a state is null or not defined then the chain of multiplication ceases.
An image can be put into absolute space by having a space property be an empty inline index.
"space" : {}
Compare with the #lights, #sounds, #controls, and #graphics space property.
state[edit]
A texture transformation matrix. Either a 16 number array constituting a 4x4 transform, or the number 1 indicating an identity matrix, or the number 0 indicating a collapsed (zero-point) matrix.
The #graphics namespace also defines a state property (which is what you may be looking for). The semantics are virtually identical, however an application may implement them to different degrees.
Note that "collapsing" the matrix by setting it to 0 (singular) is one way to animate the texture (and textures in its sub-#space) out of existence (it is the CSS equivalent of "{display:none}" ) which will affect all references to the texture. It is not identical to a zeroed matrix, which alone would probably get you the colour of the texture at (0,0). This behavior is a bit odd, but it is in line with graphics state property, where it makes a little more sense, at least for primitives with area, Ie. non-point, non-line.
scale, rotate, translate, skew[edit]
These four properties are taken together to compose the #state property. The composition is performed in software. If any of these properties is defined the value of state will be computed and overwritten.
The four properties are each arrays of 2 or more numbers describing the scale, rotation, translation, and skew factors of the computed state matrix.
paints[edit]
Each item of the paints namespace is a graphical image that defines one or more masks where each pixel can belong to one and only one mask and a set of operations over each mask. The #materials namespace includes the per texture #paint property with the assumption that it will be used to augment the colour of the textures; for purposes of reuse and or dynamic user customization. Think "palette swapping" on steroids or custom (user defined) paint jobs of any kind.
The pixel data of the image must be in the form or a #url where a url is an index into the #externals namespace for a typed image url.
<"paint wells"...>[edit]
Where <"paint wells"...> is understood to be any number of object properties containing an #rgb property. Conceptually each mask is like a well in a painter's palette. Each rgb corresponds to the rgb values of one of the masks comprising the paint image. If the rgb of a well and mask match then that well will be applied to any fragment (pixel) falling within that mask.
A typical route for an application would be to load a texture to be operated on and the mask into samplers so to be accessible to a shader program. Then the app would proceed to render the resulting texture by drawing one well at a time by sampling the mask, and discarding any samples where the distance between the sample and the rgb property is larger than some arbitrarily small number.
If no properties exist in the well then the application should assume the well makes no preset alterations. An application may define any number of operations, for example; "desaturate": true. There are no suggestions or guidelines at this time as to what kind of operations should be made available.
Note: An application is unlikely to assign special meaning to a "well" property's key, but it is free to do so. However only <"paint well"...> properties should contain #rgb properties, so that a keyword filter is not required to iterate over the wells.
sounds[edit]
Each item of the sounds namespace is a sound effects clip in the form of a #url.
volume[edit]
A sounds volume property is a number, where any value 0 or below will be muted as close to silence as possible, and any value at 1 or higher will be played at maximum volume, whatever that may be. Any value between 0 and 1 is mapped between these extremes as desired by the client application. The default is value is 1.
source[edit]
The sound source property is a three number array indicating a point in the three dimensional sound 'space' explained below.
velocity[edit]
The sound velocity property is a three number array indicating a velocity in the three dimensional sound 'space' explained below.
space[edit]
The sound space property is a #graphics index. The sound source (above) is relative to this space. The default space for a sound is that of the sound "above" it in the namespace in terms of nesting, as opposed to listing.
If no space is defined and no sound exists above then the sound is played as recorded.
A sound can be played as recorded by having a space property be an empty inline index.
"space" : {}
lights[edit]
Each item of the lights namespace is a lighting effect.
model[edit]
The light model property is a character string indicating a desired lighting model. Models are application defined.
source[edit]
The light source property is a four number array or a null or undefined value.
By default something like the "classical" lighting model is recommended. Lights with null sources are global illumination to be summed together as a basis for a global ambient colour baseline. Then the incident values of lights with sources are added to arrive at a per vertex or per pixel light level. The fourth number is a pseudo-homogeneous coordinate differentiating between point (at 1) and directional (at 0) light sources.
shape[edit]
The light shape property is a four number array defining the attenuation of the light. The default attenuation is a constant attenuation of 1.0. Meaning the light should be flat and fully saturated across infinite space.
By default something like the "classical" lighting model is recommended. The first number is constant attenuation. The second is linear. The third is quadratic. The fourth value is taken to be an arbitrary cutoff distance.
shade[edit]
The light shade is an object containing an #rgb property defining a single colour for the light to emit. This is the bare bones colour scheme for a light. The default is black.
space[edit]
The light space is a #graphics index. The light #source (above) is relative to this space. The default space for a light is that of the light "above" it in the namespace in terms of nesting, as opposed to listing.
If no space is defined and no light exists above then the light is in global space.
A light can be put into global space by having a space property be an empty inline index.
"space" : {}
controls[edit]
Each item of the controls namespace is a visualization of controller of some kind used by artists or AI scripts.
point[edit]
The control point property indicates the need for a point sprite to act both as a label, handle, and point of focus for the user.
The point property can come in almost every form available to JSON:
- A null value. No point is displayed.
- A boolean, true or false value. If true a point will be generated at (0,0,0) in the control's #space. If false, no point is displayed.
- A number. The point will be represented by this number. The client application may take some liberties with the actual presentation.
- A character string. The point will be represented by the character string. The application should render the character string precisely.
- An object. A point is displayed. The application may use the properties of the object to further elaborate upon the appearance of the point. At this time there are no guidelines for the content of the object.
title[edit]
The control title property is a character string. It is a description of the control. If the #point property is defined, the title may be used as a tooltip or extended label.
space[edit]
The control space is a #graphics index. The control #point (above) is relative to this space. The default space for a control is that of the control "above" it in the namespace in terms of nesting, as opposed to listing.
If no space is defined and no control exists above then the control is in global space.
A control can be put into global space by having a space property be an empty inline index.
"space" : {}
scripts[edit]
Each item of the scripts namespace is a scripting resource of some sort: probably a program of some kind. Probably a shader program. An application will usually provide default scripts so that the scripts namespace is not necessary. An application may also prefer to use only its own scripts, ignoring the scripts namespace altogether.
At this time no application makes use of the scripts namespace. The #materials #shaders property indexes into the scripts namespace however neither does any application honor this property as of yet. So no guidelines have been devised for the scripts namespace. At a minimum a #url or #ref property may indicate an external resource to be used as a script. A text property might allow for the script to be included directly in the JSOM resource. You might also want to be able to compose a script from many subscripts by way of the scripts sub-listing property. See #<namespace> for details on how this might work.
semantics[edit]
Each item of the semantics namespace defines the "semantics" of different identifiers, variables, functions, and preprocessor macros, that are meaningful to the assembly of graphical shaders: micro programs used to generate/render primitives, vertices, and fragments (pixels) in programmable video hardware.
This is a very brittle aspect of modern day graphics programming. The power of programmable hardware is revolutionary, however high level standards have yet to emerge a decade since this this became the way we do things. Nevertheless this is our reality, and for the large part the organisation of the JSOM schema should be very familiar to anyone accustomed to working on this end of the modern day graphics "pipeline".
<"semantics"...>[edit]
Where <"semantics"...> is understood to be any number of identifiers that may appear in a shader program. The values of each is an object. The properties of this object represent different shader languages and or profiles, such as GLSL. The name of one such property might be "glsl" and the value will be the semantic definition of the identifier for the GLSL profile.
For example, the default shader regime for an application might recognize the POSITION semantic for the position of the vertex in a vertex shader. The application may provide a default semantic, such as, "vec4(position,1)". If you choose to use the default vertex shader, then you might want to modify this behavior to be something like "vec4(mix(position,tweenpos,tween),1)" if you need the shader to do some "tweening" for you. The default shader may already provide the inputs: tweenpos and tween, or it may parse your semantics and decide that the inputs should be added to the default shader. When the shader program is compiled your semantics will be substituted for the POSITION macro in the shader. If the default shaders are not desirable, you may be able to provide your own #scripts compatible with the #materials #shaders property.
Note, the semantics namespace does not have to be limited to shader programs. Applications may use it freely when in need of solutions in any problem domain.
arrays[edit]
Each item of the arrays namespace is a flat and (probably) homogeneous array of data. The data is more than likely numbers, and there is more than likely a lot of if.
An application should never access an array's data directly, for instance to discover some properties of a graphic's geometry. To do so is a breach of one or more of the unspoken design philosophies of the JSOM schema! On the other hand, an application may do something like render a graphic to a texture and read back the values from the texture. So for example, if your application wants to find a point of intersection between a ray and a graphic, it can not dig into the data arrays that take part in the graphic, but it can render the graphic (eg. to a planar texture from the perspective of the ray) and read back the depth value where the ray is expected to come in contact with the graphic.
What an application can do, is investigate the data in a way that is (practically) devoid of context. Eg. to determine: that the data is in an appropriate format, what data type(s) are represented, that the data can be represented by a 16bit (vs. 32bit, etc) data type or not.
data[edit]
The data property is a single array of data. The utility / semantics of the data is not defined and should not be assumed under any circumstances.
index[edit]
The index property indicates that the data is an index. It is a boolean value, true or false. The most likely use of an array item is to feed an "array buffer" or "array element buffer" as defined by the OpenGL standards (or "vertex buffer" and "index buffer" as described by Direct3D) in which case index should be defined true if the array is for use by an element (or index) buffer (and may be defined false or not defined otherwise).
attributes[edit]
Items of the attributes namespace almost represent a direct mapping to glVertexAttribPointer. In short an attribute is one channel of your per vertex data for your #graphics. The attribute data is taken from one of #arrays. The data can be sequential or interleaved, and need not begin at the start of the array data. The current guidelines assume that the the array data is homogeneous (of one type) and so unless some more properties are defined for heterogeneous arrays, then we are limited to this. It is not clear (to the author typing anyway) if the current ECMAScript (JavaScript) standards allow for heterogeneous arrays, however the WebGL implementation of glVertexAttribPointer does allow for byte aligned entry points into the array.
array[edit]
The array property is a singular index into the #arrays namespace. This aforementioned array. The array's #index property must NOT be defined to be true, nor should it evaluate to any other value than false.
semantic[edit]
The semantic property IS NOT an index into the #semantics namespace. This is a little confusing, but it is the actual "semantic" identifier of the attributes. Semantics are kind of conventional things. They are technically application defined. GLSL does not even have its own framework for semantics (as HLSL does) but you kind of need one if you need any degree of interoperability / familiarity in your shaders.
Typical semantic conventions for your basic attributes are "position", "normal", "texcoord0", for example. OpenGL knows how to find attributes by their identifiers. Identifier is a proposed property, which an application is free to implement, but its easier to assume that the identifier is synonymous with the semantic. Bottom line a semantic communicates intent, an identifier does not. If you don't provide a semantic then you will have to roll your own shaders for certain, assuming an application implements an identifier property so that the app can find your attribute at all.
Note. The value of the semantic property is not a constant, so it should be lowercase.
size[edit]
The size property is the size of the attributes in whatever units the array is in. So for a 3D position coordinate, the size is 3, or it may be 4 for a homogeneous 3D position coordinate. Applications may expect certain semantics to always be the same size, or the application may be more forgiving. Consult the applications documentation (if there is any) the default size is 3, since that is most common.
stride[edit]
The stride property is the number of units between each attribute in the array, for interleaved attributes. The default is 0, which is normally interpreted to be whatever the size property is taken to be.
start[edit]
The start property is the location of the first attribute in the array in whatever units the array is in. Note by "units the array is in" we mean 1 unit per data point. This is why it is important that we assume the array is homogeneous. Hint. You don't even know what the data type of your array will ultimately be coerced into.
Warning: notice that there is no property for the number of attributes. This is something hardware is unconcerned with; in other words it is up to you to not overflow your buffers, however if your application is implemented in a WWW browser, these environments are usually fairly strict, and will almost certainly check for you / refuse to play with your arrays if they fail to pass muster.
elements[edit]
Each item of the elements namespace is almost a direct mapping to glDrawElements. If #attributes describe the vertex data, elements describe facets of the geometry, triangles, wireframes, point sprites, etc. A triangle element for instance is 3 numbers, one per vertex, where each number is a subscript into the bound vertex attributes.
The attribute data is taken from one of #arrays. The data must be sequential but need not begin at the start of the array. The current guidelines assume that the the array data is homogeneous (of one type) and so unless some more properties are defined for heterogeneous arrays, then we are limited to this. It is not clear (to the author typing anyway) if the current ECMAScript (JavaScript) standards allow for heterogeneous arrays, however the WebGL implementation of glDrawElements does allow for byte aligned entry points into the array.
array[edit]
The array property is a singular index into the #arrays namespace. This aforementioned array. The array must contain the elements, and the array's #index property must be defined to be true.
mode[edit]
The mode property is a constant (see #Constants) describing the elements' type. "TRIANGLES" for triangles, "LINES" for lines. The default is "POINTS" since that is most basic / harmless. These constants correspond to glDrawElements. Note QUADS and POLYGONS are not part of the OpenGL ES specification. These constants remain the same even if the application is not OpenGL based. It is up to the application to translate into its native platform.
start[edit]
The start property is the location of the first element in the array in whatever units the array is in. Note by "units the array is in" we mean 1 unit per data point. This is why it is important that we assume the array is homogeneous. Hint. You don't even know what the data type of your array will ultimately be coerced into.
count[edit]
The count property is the number of data units to iterate over. For example, if the #mode is "TRIANGLES" each triangle is made up of 3 units, so the count is the number of triangles times (multiplied by) 3. Needless to say, the count should not overflow/exceed the array.
materials[edit]
An item in the materials namespace really represents a full blown shader program complete with texture resources. Chances are a JSOM rendering application will do its best to sort things first by passes (see #pass) and then by materials, therefore you might think twice about trying to animate any indexes into the materials namespace (or passes for that matter).
The impression you get is the biggest performance hit you will take is swapping out your shaders and textures. In so far as this is true, a JSOM resource generator should strive to get as many graphics as possible aimed at as few materials as possible.
shaders[edit]
The shaders property is an array with room for 3 indices into the #scripts namespace. One per each type of shader; vertex, fragment, geometry respectively. Note. OpenGL ES does not include geometry shaders. With the shaders property a resource can specify its own shader regime, custom made, from scratch.
Note. An application should always provide default shaders, and is not required to support the shaders property. See #scripts for details.
semantics[edit]
The semantics property is an array with room for 3 indices into the #semantics namespace. The semantics are not not joined together, but rather specified first for the vertex shader, second for the fragment shader, and third for a geometry shader. Note. OpenGL ES does not include geometry shaders.
The "semantics" themselves should be taken both from the item itself and any items comprising the item's sub-list (see #Items and Lists) and any item's comprising those items' sub-lists, and so on.
These semantics used will differentiate the material usually resulting in the generation of a new shader program. An application may cache programs in an attempt to share them across materials with identical semantics and #shaders (explained above).
texture[edit]
The texture property is an array of indices into the #images namespace. Each image, and any sub-images (see #Items and Lists) will fill up the available multi-texture slots proceeding recursively. It is not recommended to have non-leaf textures in the images namespace for clarity sake, but the appropriate order is to go 0 first, 0.0 second, 0.1 third, then back up to 1 for the 4th multi-texture slot.
paint[edit]
The paint property is an array of indices into the #paints namespace, one paint per texture index in the #texture property above. The "paint" should be applied to the textures. If desirable users can be able to tweak the paint interactively.
diffuse, emissive, ambient, specular[edit]
These properties are recommended. Each one should be an object with an #rgb property permitting a colour to be defined for the "classical" materials & #lights model. Lights may also support parallel channels if the single #shade property is deemed inadequate. In practice many lights may be loaded up into a shader; where in having four channels per light can add up both in terms of performance and program registers. On the other hand 4 per material is a comparably modest investment.
Other properties, Eg. "specular:{power:0.5}" should be accommodated as needed.
further shader variables[edit]
Any shader/render states that can be defined by #graphics should also be permitted to appear in materials. Eg. #opacity. These include the suggested #diffuse, emissive, ambient, specular properties above (but not any others) and any purely user derived shader variables. The values in the material should be both the initial values and the default values used whenever the self-same property is undefined or null for a graphic "belonging" to the material (by way of the graphic's #sides property).
graphics[edit]
Each item in the graphics namespace is a 3D coordinate system consisting of zero or more graphical elements.
pass[edit]
When graphics are overlaid onto a display device it is often the case that the order in which that is done is critical to achieving the correct results. For example, graphics are usually sorted into two camps, opaque, and not-opaque. The opaque graphics are displayed first, and then the not-opaque graphics are blended over those in a second pass.
The pass property then allows graphics to be sorted into multiple passes as explained above. The first pass is 0, the second pass is 1, and so on. The default is 0.
sides[edit]
The sides property is a two index array into the #materials namespace assigning a material to the front side and back side of the graphic respectively. If at least one of the indices is not present then no graphics are displayed. Note that a graphic may simply be an empty/intermediate coordinate system with no graphics to display in the first place.
Sides assumes that the graphic has no volume. It is simply a collection of triangles, with a front side and a back side as if cutout of a piece of paper. The back sides of these triangles collectively comprise the back side of the graphics.
Note. If both indices are equal (the indices themselves should be equal) then both sides are displayed simultaneously. If sides are not equal (and both are defined and non-null) the the graphic will almost definitely be displayed twice, once per side. If your need is to have a single shader rendering both sides simultaneously but non-identically, then the graphic should have both sides equal and you should look into what two-sided shader options are available to your target application..
An application should implement a generic back face shading feature that can be turned off/on by the the user. Ie. a JSOM resource should not take it upon itself to fill in its back faces just to avoid the back faces not being displayed.
attributes[edit]
The attributes property is an array of indices into the #attributes namespace. If attributes are not defined or null the default behavior is to use every attribute available to the resource in which the graphic is defined.
Attributes are a prerequisite to having a graphic with visual elements. For instance, an attribute with the "position" semantic is a virtual necessity to achieve almost any manner of visual effect.
primitives[edit]
The primitives property is an array of indices into the #elements namespace. The elements will be displayed per the #sides property with the attributes of #attributes.
Hint. These properties (outlined above) taken together constitute the meat of your graphics. Compare to #wireframes below.
wireframes[edit]
The wireframes property is an array of indices into the #elements namespace. Wireframes differs from primitives in that it is understood that primitives is the actual representation of the graphics, and that wireframes is a visualization of the data underpinning the graphic. The wireframes elements are not displayed under normal circumstances, but can be turned on by the application if desired and supported and provided.
clearance[edit]
The clearance property is a three by two multi-dimensional array, where the first element is a minimum and maximum of the "X" axis of the 3D coordinate system, the second element is the same for the "Y" axis, and the third for the "Z" axis; together describing the outermost reaches of the graphic in global space.
The "bounding boxes" will be unioned together and used to figure the center and radius of a collection of graphics for the purpose of presenting it dead center of the display to the end user.
If the resource including the graphics is referenced by an outer resource which places the resource off center of the top-level global space, the clearance properties are only ever translated and scaled (never rotated or skewed) into the outer resource's global space.
Clearance properties should not be used for any other purpose than defined above. It is sufficient for a resource to define a clearance for only one of its graphics, as long as the graphic encompasses all other graphics. Clearance should also take into account all animations (#tracks) as clearance is not a factor in animation (it is considered undesirable for the "camera" to shift about from animation to animation).
space[edit]
The space property is an index into another graphic from which the #state property (next section) is taken to be relative to / "multiplied" with. The default space for a graphic is the graphic "above" it in the namespace in terms of nesting, as opposed to listing. If a state is null or not defined then the chain of multiplication ceases.
A graphic can be put into absolute (resource global) space by having a space property be an empty inline index.
"space" : {}
Compare with the #lights, #sounds, #controls, and #images space property.
state[edit]
The state property communicates a spatial transformation matrix. Either a 16 number array constituting a 4x4 transform, or the number 1 indicating an identity matrix, or the number 0 indicating a collapsed (zero-point) matrix.
Note that "collapsing" the matrix by setting it to 0 (singular) is one way to animate the graphic (and graphics in its sub-#space) out of existence (it is the CSS equivalent of "{display:none}" ). The #images #state property also follows this convention, albeit a little more awkwardly. A zeroed matrix is unrecoverable for elements with area. It may have some meaning to point and line elements.'
scale, rotate, translate, skew[edit]
These four properties are taken together to compose the #state property. The composition is performed in software. If any of these properties is defined the value of state will be computed and overwritten.
The four properties are each arrays of 3 numbers describing the scale, rotation, translation, and skew factors of the computed state matrix. The rotation should be in radians, and equivalent to an X*Y*Z rotation matrix. Rotation may also be a 4 number array to be interpreted as a quaternion with the 4th number serving as the "scalar" component.
weight[edit]
The weight property is an array of indices into the #templates namespace where each template is expected to have a #state and or #space property, or neither. Other properties of the template are ignored.
The default behavior is to use the graphic's own state and space properties.
Multi-state #shaders have many advantages not (yet) enumerated here.
blend[edit]
The blend property is a two #Constants array. Each constant is taken from glBlendFunc to determine the source and destination blend factors respectively.
opacity[edit]
The opacity property is a scale factor to be applied to the alpha channel of the fragment colour prior to blending. Opacity can be combined with #blend to achieve a wider variety of basic blending behaviors. The default value is 1.
light[edit]
The light property is an array of indices into the #lights namespace, where each light takes part in lighting the graphic.
Lights below the lights indexed in terms of nesting, as opposed to listing, are also included in the graphics' lighting.
The default behavior is to use the lights of the graphics above in terms of nesting, as opposed to listing, or in the case of the top level graphic all lights available to the resource are to be used.
You can always disable lighting for a graphic (and its sub-graphics) by setting light to a single empty inline index.
"light" : [{}]
evaluators[edit]
Items of the evaluators namespace establish interpolation like behavior on a per property basis. Traditionally this sort of thing is used for animation and curve/surface generation and tessellation.
namespace[edit]
The namespace property restricts the evaluator to properties of the given namespace. It should be implemented by applications if any property key is able to be animated and spans namespaces. The default behavior is to not take the namespace into consideration when matching property keys.
<methods...>[edit]
Where <methods...> is understood to be any number of key value pairs, where the key is to be matched with any property from any namespace (unless restricted by #namespace; explained above) and the value is an application interpreted character string which communicates an evaluation method which should be applied to a matching property; see #keyframes for example. For instance the value "lerp" might indicate a point to point linear interpolation method.
keyframes[edit]
Each item in the keyframes namespace describes a period of time in the course of an animation; where an "animation" is defined as the changing of item properties over time. See #Items and Lists.
#graphics that do not take part in keyframes are not displayed when being animated. Therefore any graphic which is intended to be visible should belong to a keyframe which persists during the time in which the graphic should be visible. If a graphic belongs to overlapping keyframes, the graphic will only be displayed once as long as the keyframes overlap (as in no matter what the graphic only appears once).
If the properties (see #<namespaces...> below) of the keyframes overlap during the course of an animation then those properties will be undefined.
timerange[edit]
The timerange property is a two number array delimiting the beginning and end of the keyframe. If the beginning comes after the end (read: is greater than) the keyframe will be out of time so to speak and can never take part in an animation.
<namespaces...>[edit]
Where <namespaces...> is understood to be any number of property key value pairs, where the keys of each property are one of the available namespaces ("images", "materials", "graphics", "lights", "sounds", etc) and the values are each an array of indices into the #templates namespace, where the properties of the templates are to be used by each item of that namespace belonging to a keygroup (by way of its #keygroups (property)) which includes the keyframe.
Each subscript of the index arrays is assumed to correspond across the participating namespaces, so that you can conceptualize them as "channels". The properties of the first subscript per namespace carry over into the subsequent subscript and so on unless a new value for the property key is provided. Any <namespaces...> array that is shorter than the longest array will be extended so that all arrays across <namespaces...> are the same length.
Applications would be wise to provide an always available #shader variable (the identifier "tween" is recommended) in the form of a scalar value marking the point in the range [0,1] for the keyframe being displayed so that a resource is never forced to include its own tween properties into every single template index.
Reminder: Recall that indices may be inline objects (see #Indices, Index singular).
A simple keyframes resource:
{ "keyframes": [ { "timerange": [1,2], "graphics": [ { "state": [ 0.979970,0.029206,0.196993,0.000000, -0.029889,0.999553,0.000490,0.000000, -0.196891,-0.006368,0.980405,0.000000, 0.066729,-0.014893,-0.031111,1.000000 ] } ] },... ] }
evaluators (property)[edit]
The evaluators property is an array of indices into the #evaluators namespace. The #<methods...> of the evaluators are to be applied to any matching properties per each template of #<namespaces...> (described above) each time the keyframe is sampled (see #samples below)
Note: it is best to go to almost any length to avoid using evaluators. Consider doing the sampling offline as a preprocess (generating a new "unevaluated" keyframe per sample) if your target environment is not well suited to real-time computation, eg. JavaScript. Your "bloated" resources may perform much better albeit at the cost of consuming much more memory. An application should not make the decision to presample a resource unless a user explicitly requests that this be done on the user's behalf. Assume the resource knows what it wants.
samples[edit]
The samples property is an array of numbers per each subscript of the #templates index arrays of #<namespaces...> (described above). Each sample marks a point in time in the same timescale as #timerange. The samples are provided as arguments to the evaluation #<methods...> of the #evaluators (property). The number of samples may be greater than the (maximum) number of subscripts as long as the excess is an even number, and the samples themselves need not fall within the timerange of the keyframe.
Consult the documentation of the evaluation method to see how many if any samples are necessary and or required.
keygroups[edit]
Each item of the keygroups namespace is a group of #keyframes. Keyframes may be grouped for any purpose. Established purposes include grouping for the purpose of defining an animation, in the case of #key, and grouping for the purpose of defining the membership of a keyframe, in the case of the universal #keygroups (property).
keyframes[edit]
The keyframes property is an array of indices into the #keyframes namespace defining the membership of the keygroup.
timeframe[edit]
The timeframe property is a two number array delimiting the minimum and maximum times between which an animation will take place. The times correspond directly to #timerange for the keyframes in the group. Note that this property is only meaningful in the animation context (see #key).
timescale[edit]
The timescale property is a number to scale the #timerange of the keys of the groups into seconds (as in seconds, minutes, and hours). Note that this property is only meaningful in the animation context (see #key).
tracks[edit]
An item in the tracks namespace is an audio visual presentation.
title[edit]
The title property is a character string to be provided in the track listing. The default is "untitled".
key[edit]
The key property is an array of indices into the keygroups namespace. The keyframes of each indexed keygroup will be sampled. Times are taken from the keygroups or calculated from the keyframes by default.
keyclip[edit]
The keyclip property is an array of arrays of two numbers per each element of the key array. The first number is the amount of time to clip from the beginning of the keygroup. The second number is the time at which to cut the keygroup off. Defaults are time[0,infinity].
keysync[edit]
The keysync property is an array of numbers per each element of the key array. Each number is the time to begin playing the indexed keygroup. Defaults are time 0.
keytime[edit]
The keytime property is an array of numbers per each element of the key array. Each number is the speed (or scale) at which to play each key where 1 equals 1:1 seconds (as in seconds, minutes, and hours), 2 is 1:2 seconds, and so on. So that the larger the value the slower and longer the animation will become. The default value is 1.
bgm[edit]
The bgm property is an array of indices into the sounds namespace. If you need the sounds to be very robust, it is much easier for an application to play them separate from keyframes.
bgmclip[edit]
The bgmclip property is an array of arrays of two numbers per each element of the bgm array. The first number is the amount of time to clip from the beginning of the sound. The second number is the time at which to cut the sound off. Defaults are time[0,infinity].
bgmsync[edit]
The bgmsync property is an array of numbers per each element of the bgm array. Each number is the time to begin playing the indexed sound. Defaults are time 0.
bgmtime[edit]
The bgmtime property is an array of numbers per each element of the bgm array. Each number is the speed (or scale) at which to play each sound where 1 equals 1:1 seconds (as in seconds, minutes, and hours), 2 is 1:2 seconds, and so on. So that the larger the value the slower and longer the sound will become. The default value is 1.