Difference between revisions of "X3D/HTML Integration"

From Web3D.org
Jump to: navigation, search
(Summary)
 
(15 intermediate revisions by the same user not shown)
Line 1: Line 1:
Example to investigate X3D/HTML specification issues
 
  
As an illustration consider the X3DOM example [http://doc.x3dom.org/tutorials/animationInteraction/onoutputchange/example.html "OnOutputChange"]. The source for this example is reproduced below.
+
== Examples ==
  
<pre>
+
X3DOM: [[OnOutputChange Example]]
<html>
+
<head>
+
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+
    <title>X3Dom Example OnOutputChange Event</title>
+
    <script type='text/javascript' src='http://x3dom.org/release/x3dom.js'> </script>
+
    <link rel='stylesheet' type='text/css' href='http://www.x3dom.org/download/x3dom.css'/>
+
  
 +
X3DOM: [[Interactive 3D Transformations Example]]
  
<script>
+
== Summary ==
/**
+
* Uses the values of a PositionInterpolator to move another ball,
+
* but instead of just routing the values, round the y component.
+
* Thus the second ball moves like he is snapping to an invisible raster
+
*/
+
function snapBall(eventObject)
+
{
+
//Check if type and output of the eventObject are correct
+
//There may be multiple eventObjects but only one of them contains the value we need
+
if(eventObject.type != "outputchange" || eventObject.fieldName != "value_changed")
+
return;
+
+
//Get the value...
+
var value = eventObject.value;
+
//...and create a copy with the manipulated coordinates
+
var newPos = new x3dom.fields.SFVec3f(2, Math.round(value.y), 0);
+
+
//Set the newly created array as new position for the second ball
+
document.getElementById("ball2").setAttribute('translation', newPos.toString());
+
+
//Show debug information (of course the data can be used to control non x3dom-objects, too)
+
document.getElementById("posInterp").innerHTML = Math.round(value.y*100)/100;
+
document.getElementById("posSnaped").innerHTML = newPos.y;
+
}
+
</script>
+
 
+
</head>
+
<body>
+
 
+
<h1>Animate Objects with X3DOM!</h1>
+
<p>
+
    Learn how to manipulate objects using values from the output of other objects.
+
</p>
+
 
+
<div>
+
Y-Position of output field (routed to red ball): <span id="posInterp"></span><br>
+
Calculated Y-Position (set directly to blue ball): <span id="posSnaped"></span>
+
</div>
+
 
+
<x3d width='500px' height='400px'>
+
    <scene>
+
        <transform DEF="ball" translation='-2 0 0'>
+
        <shape>
+
            <appearance>
+
                <material diffuseColor='1 0 0'></material>
+
            </appearance>
+
            <sphere></sphere>
+
        </shape>
+
        </transform>
+
       
+
        <transform DEF="ball2" translation='2 0 0' id="ball2">
+
        <shape>
+
            <appearance>
+
                <material diffuseColor='0 0 1'></material>
+
            </appearance>
+
            <sphere></sphere>
+
        </shape>
+
        </transform>
+
 
+
        <timeSensor DEF="time" cycleInterval="4" loop="true"></timeSensor>
+
        <PositionInterpolator DEF="move" key="0 0.5 1" keyValue="-2 -2.5 0  -2 2.5 0  -2 -2.5 0" onoutputchange="snapBall(event)"></PositionInterpolator>
+
       
+
        <Route fromNode="time" fromField ="fraction_changed" toNode="move" toField="set_fraction"></Route>
+
        <Route fromNode="move" fromField ="value_changed" toNode="ball" toField="translation"></Route>
+
    </scene>
+
</x3d>
+
 
+
 
+
</body>
+
</html>
+
</pre>
+
 
+
Let's concentrate on a single line from this example:
+
<pre>
+
        <PositionInterpolator DEF="move" key="0 0.5 1" keyValue="-2 -2.5 0  -2 2.5 0  -2 -2.5 0" onoutputchange="snapBall(event)"></PositionInterpolator>
+
</pre>
+
 
+
It is clear that this is essentially an XML encoded line. It has the following structure:
+
 
+
* The element type "PositionInterpolator" with attributes of:
+
** DEF, with the name "move"
+
** key, with three values
+
** keyValue, with three sets of three values (the field type is MFVec3f)
+
** onoutputchange, with a function call reference
+
 
+
The last attribute above, however, is not part of the current X3D V3.3 specification. How does it arise? How might it be specified?
+
 
+
If X3D is fully integrated into HTML there will be a DOM extension associated with the specification. This extension might define a "PositionInterpolator" interface, which would inherit, probably indirectly, from the "HTML Element" interface.
+
 
+
So let's look at this interface. Let's check the WhatWG specification for the [https://html.spec.whatwg.org/multipage/dom.html#htmlelement HTMLElement] interface. I reproduce the listing from 8th June 2016 here:
+
 
+
<pre>
+
[Constructor]
+
interface HTMLElement : Element {
+
  // metadata attributes
+
  [CEReactions] attribute DOMString title;
+
  [CEReactions] attribute DOMString lang;
+
  [CEReactions] attribute boolean translate;
+
  [CEReactions] attribute DOMString dir;
+
  [SameObject] readonly attribute DOMStringMap dataset;
+
 
+
  // user interaction
+
  [CEReactions] attribute boolean hidden;
+
  void click();
+
  [CEReactions] attribute long tabIndex;
+
  void focus();
+
  void blur();
+
  [CEReactions] attribute DOMString accessKey;
+
  readonly attribute DOMString accessKeyLabel;
+
  [CEReactions] attribute boolean draggable;
+
  [CEReactions, SameObject, PutForwards=value] readonly attribute DOMTokenList dropzone;
+
  [CEReactions] attribute HTMLMenuElement? contextMenu;
+
  [CEReactions] attribute boolean spellcheck;
+
  void forceSpellCheck();
+
};
+
HTMLElement implements GlobalEventHandlers;
+
HTMLElement implements DocumentAndElementEventHandlers;
+
HTMLElement implements ElementContentEditable;
+
</pre>
+
 
+
The important part for our purposes are the last three lines. That is, what other interfaces HTMLElement implements.
+
 
+
There are three:
+
* GlobalEventHandlers
+
* DocumentAndElementEventHandlers
+
* ElementContentEditable
+
 
+
Do any of these cover the "onoutputchange". No they don't. How does it arise then?
+
 
+
Searching the X3DOM code base (available on GitHub) we find that this is defined in the file [https://github.com/x3dom/x3dom/blob/master/src/nodes/Core/X3DNode.js X3DNode.js]. There is a function defined as part of the X3DNode class called postMessage, as follows:
+
 
+
<pre>
+
            postMessage: function (field, msg) {
+
                // TODO: timestamps and stuff
+
                this._vf[field] = msg;  // FIXME; _cf!!!
+
                var listeners = this._fieldWatchers[field];
+
 
+
                var that = this;
+
                if (listeners) {
+
                    Array.forEach(listeners, function (l) { l.call(that, msg); });
+
                }
+
 
+
                //for Web-style access to the output data of ROUTES, provide a callback function
+
                var eventObject = {
+
                    target: that._xmlNode,
+
                    type: "outputchange",  // event only called onxxx if used as old-fashioned attribute
+
                    fieldName: field,
+
                    value: msg
+
                };
+
 
+
                this.callEvtHandler("onoutputchange", eventObject);
+
            },
+
</pre>
+
 
+
This relates to the [https://github.com/x3dom/x3dom/blob/master/src/nodes/Interpolation/PositionInterpolator.js PositionInterpolator] implementation, where there is a function fieldChanged:
+
 
+
<pre>
+
            fieldChanged: function(fieldName)
+
            {
+
                if(fieldName === "set_fraction")
+
                {
+
                    var value = this.linearInterp(this._vf.set_fraction, function (a, b, t) {
+
                        return a.multiply(1.0-t).add(b.multiply(t));
+
                    });
+
 
+
                    this.postMessage('value_changed', value);
+
                }
+
            }
+
</pre>
+
 
+
Now we can see the connection. When the ''set_fraction'' inputOnly field is changed an output value is calculated, and a message posted saying that the ''value_changed'' outputOnly field now has the value "value". When the postMessage function is called, it will create an event object and call the onoutputchanged event.
+
 
+
Now we understand how it is implemented we can consider specification possibilities. This event is generated as part of the X3DNode class. Therefore, it may be applied to any node. A definition, therefore, has to be at the X3DNode level. Hence, there needs to be a DOM extension to cover this event at that level. So we have to define an extended interface,  perhaps called X3DElement. It might inherit from HTMLElement. All other X3D node interfaces would inherit from X3DElement.
+
 
+
So the X3DElement interface might now be:
+
 
+
<pre>
+
interface X3DElement : HTMLElement {};
+
 
+
X3DElement implements X3DEventHandlers;
+
</pre>
+
 
+
In turn, the X3DEventHandlers might be defined as:
+
 
+
<pre>
+
[NoInterfaceObject]
+
interface X3DEventHandlers {
+
  attribute EventHandler onoutputchanged;
+
};
+
</pre>
+
  
 
So, specifying the integration of X3D into HTML requires a lot more than a simple encoding. Assuming we consider generating an ISO/IEC specification, should we be generating a 19776 series document. I believe the answer is no. We need a much more overarching document. I suggest a 19775-3 document, perhaps entitled "X3D Embedding in HTML" or "X3D Integration with HTML", or some such.
 
So, specifying the integration of X3D into HTML requires a lot more than a simple encoding. Assuming we consider generating an ISO/IEC specification, should we be generating a 19776 series document. I believe the answer is no. We need a much more overarching document. I suggest a 19775-3 document, perhaps entitled "X3D Embedding in HTML" or "X3D Integration with HTML", or some such.
Line 218: Line 22:
 
# Fields - DOMStrings vs X3D types
 
# Fields - DOMStrings vs X3D types
 
# Event models
 
# Event models
 +
# DEF/USE vs ID/IDREF
 
# Capitalization
 
# Capitalization
 
# Namespace
 
# Namespace
 
# Scripts and Prototypes
 
# Scripts and Prototypes
 
# (any I have missed)
 
# (any I have missed)
 +
## DOM Extension
 +
## Other event handlers
 +
## Closing tags
 +
## X3D tag attributes
  
 
We should look at each, and understand the implications for both 19775-1 and the new specification.
 
We should look at each, and understand the implications for both 19775-1 and the new specification.
 +
 +
So leaping ahead, we could specify every node.
 +
 +
The GitHub repository for X3DOM contains small js files, in a folder structure. For downloading these seem to be combined into a single file. So if it contained all the nodes, it would be a large file. This is undesirable, particularly for mobile devices. So, can it be broken down into subunits?
 +
 +
XML3D are taking the approach of breaking down using a vertical stratification. This means they define a small core, which also incorporates an API, and then can define other nodes in terms of that API. So, presumably you have a relatively small core, and need additional downloads to add to it.
 +
 +
What about X3D? We have been talking about an HTML profile. We already have components. So our stratification is more horizontal. We could foresee a relatively small main file, for the basic HTML profile. Then an author could specify additional components, which would require a small separate download for each component. Is this a practical solution? Can subsequent js files make reference to functionality downloaded in a primary js file? The answer is believed to be yes, but confirmation is required.
 +
 +
Assuming the answer to the last question is yes, then we have to:
 +
 +
* Define an HTML profile.
 +
 +
What about Web components? How do they fit into the picture?
 +
 +
There are:
 +
* Custom Elements - Is this useful for X3D prototypes?
 +
* HTML Imports - Is this useful for X3D Inlines?
 +
* Templates - Is this useful for X3D prototypes?
 +
* Shadow DOM - This might solve the namespace problem
 +
 +
W3C Validator plugin would be a good idea to enable X3D validation in HTML

Latest revision as of 17:05, 15 June 2016

Examples

X3DOM: OnOutputChange Example

X3DOM: Interactive 3D Transformations Example

Summary

So, specifying the integration of X3D into HTML requires a lot more than a simple encoding. Assuming we consider generating an ISO/IEC specification, should we be generating a 19776 series document. I believe the answer is no. We need a much more overarching document. I suggest a 19775-3 document, perhaps entitled "X3D Embedding in HTML" or "X3D Integration with HTML", or some such.

I see the following actions:

  1. Review all X3DOM code, and understand the implications for specification.
  2. Review all Cobweb code, and understand the implications for specification.
  3. Review other 3D implementations, to see what lessons can be learned.

As these are reviewed we should start generating interface definitions. There's nothing like putting pen to paper, or pressing keys, and generating some technical details as we go. These can be short interface definitions, as above.

Furthermore, we are already aware of a number of general issues:

  1. Fields - DOMStrings vs X3D types
  2. Event models
  3. DEF/USE vs ID/IDREF
  4. Capitalization
  5. Namespace
  6. Scripts and Prototypes
  7. (any I have missed)
    1. DOM Extension
    2. Other event handlers
    3. Closing tags
    4. X3D tag attributes

We should look at each, and understand the implications for both 19775-1 and the new specification.

So leaping ahead, we could specify every node.

The GitHub repository for X3DOM contains small js files, in a folder structure. For downloading these seem to be combined into a single file. So if it contained all the nodes, it would be a large file. This is undesirable, particularly for mobile devices. So, can it be broken down into subunits?

XML3D are taking the approach of breaking down using a vertical stratification. This means they define a small core, which also incorporates an API, and then can define other nodes in terms of that API. So, presumably you have a relatively small core, and need additional downloads to add to it.

What about X3D? We have been talking about an HTML profile. We already have components. So our stratification is more horizontal. We could foresee a relatively small main file, for the basic HTML profile. Then an author could specify additional components, which would require a small separate download for each component. Is this a practical solution? Can subsequent js files make reference to functionality downloaded in a primary js file? The answer is believed to be yes, but confirmation is required.

Assuming the answer to the last question is yes, then we have to:

  • Define an HTML profile.

What about Web components? How do they fit into the picture?

There are:

  • Custom Elements - Is this useful for X3D prototypes?
  • HTML Imports - Is this useful for X3D Inlines?
  • Templates - Is this useful for X3D prototypes?
  • Shadow DOM - This might solve the namespace problem

W3C Validator plugin would be a good idea to enable X3D validation in HTML