xml3d / xml3d.js

The WebGL/JS implementation of XML3D
Other
75 stars 25 forks source link

Xflow update somehow unreliable when toggling data-src attribute #104

Closed j4yk closed 9 years ago

j4yk commented 9 years ago

I have the following setup to render a bunch of boxes:

<asset id="boxes">
    <assetdata name="mapping" compute="dataflow['df.xml#makeboxes']">
        <data id="extent-mapping" src="extent.json"/>
        <data id="height-mapping" src="height.json"/>
        <data id="color-mapping" src="color.json"/>
    </assetdata>
    <assetdata name="boxindex" compute="dataflow['df.xml#boxindices']">
        <int name="boxindex">0</int>
    </assetdata>
    <assetmesh includes="mapping boxindex" type="tristrips">
    </assetmesh>
</asset>
<model src="#boxes" id="0" >
    <assetdata name="boxindex"><int name="boxindex">0</int></assetdata>
</model>
<!-- more of the models -->

df.xml#makeboxes takes the custom attributes from the three json files and creates the box vertices with position, normal and color, while df.xml#boxindices creates the appropriate index values for each individual box.

The initial rendering looks fine. Now I change the height-mapping by document.getElementById("height-mapping").setAttribute("src", "height2.json"). The boxes all disappear and reappear shortly after with new heights (i. e. changed position attributes). So far so good.

For the following, the behavior seems not to be really deterministic. If I toggle the height-mapping between the two height-jsons at some point I always get: Mesh Error: Mesh does not have 'position' attribute. for each model/box and all boxes disappear.

So far it has occurred on those different occasions:

Usually the other file still yields the correct result, i. e. I can toggle between a working rendering and the errors. But sometimes none of them work after the errors first appeared.

Can you imagine a case where Xflow "forgets" to do its computation when the src-attribute is toggled between two files?

The behavior also occurs with three different files. Only one can usually be rendered after some toggling.

However, to complicate the matter, I was not able to reproduce it with this simpler example:

<asset id="test">
    <assetdata name="mapping" compute="position = xflow.add(pos, offset)">
        <float3 name="offset">-0.5 0 0 -0.5 0 0 -0.5 0 0</float3>
        <data id="positions" src="positions.json"/>
        <float3 name="normal">0 0 1 0 0 1 0 0 1</float3>
    </assetdata>
    <assetmesh includes="mapping" type="tristrips">
    </assetmesh>
</asset>
<model src="#test" id="0" >
</model>

...and toggling between positions.json and positions2.json which both contain a pos array for a single triangle. Toggling repeatedly does not produce errors here.

I assume that my Xflow operators are correct since I get a successful rendering for each file at least once. Is there some kind of result caching at work which fails here?

ksons commented 9 years ago

Hi,

it's kind of hard to answer your questions without having seen what actual happens. However, here are some comments which might help solving your issue:

The Mesh Error should not appear. The flow graph is set to loading and will not execute any calculations or complain about missing data until all sub-trees have been loaded

The asset model is currently implemented for its main use-case: Overriding values inside a fixed structure has minimal overhead. However, since you (potentially) change the structure by changing the source of the data, you trigger a complete rebuild of the asset structure (which is why you don't see the result for a second). This involves many maps that the garbage collector may not able to clean up fast (or at all). So the crash might result from a simple out of memory in the tab (given you create a lot of boxes :white_medium_square:

We have other users that use assets in a similar way (a way we originally not intended), thus we were already discussing if we try optimizing structural changes in assets.

However, one possible solution could be to use simple meshes instead. If you don't instance your "'#test" multiple times it's likely that you have less issues.

Another way to not introduce structural changes would be to use sequences. With sequences you could load both height.json into your application an switch between both without triggering a structural change. And you could even interpolate between the positions. If the height data is a stream, you should consider setting the positions via API. Here are examples for both approaches:

Sequences: http://xml3d.github.io/xml3d-examples/examples/xflowSequentialMorph/xflow-morph.html API: http://xml3d.github.io/xml3d-examples/examples/scriptValue/scriptValue.html

Hope that helps.

j4yk commented 9 years ago

Actually, I get the same behavior (temporarily disappearing boxes, next time Mesh errors) with the following structure:

<defs>
    <data id="mapping" compute="dataflow['df.xml#makeboxes']">
        <data id="extent-mapping" src="extent.json"/>
        <data id="height-mapping" src="height.json"/>
        <data id="color-mapping" src="color.json"/>
    </data>
</defs>
<mesh type="tristrips" id="0" compute="dataflow['df.xml#boxindices']">
    <data src="#mapping" />
    <int name="boxindex">0</int>
</mesh>
<!-- more meshes -->

On the JavaScript console:

> document.getElementById("height-mapping").setAttribute("src", "height2.json")
undefined
(boxes render correctly with new heights)
> document.getElementById("height-mapping").setAttribute("src", "height.json")
undefined
xml3d.js:1403 Mesh Error: Mesh does not have 'position' attribute. 
xml3d.js:1403 Mesh Error: Mesh does not have 'position' attribute. 
...

However, now it is consistently impossible to show one particular height mapping a second time. I can no longer switch back to a working version (except for reloading the page).

The browser process does not actually crash, I justed abused the word to describe the failing of the rendering with the Mesh errors. ;-)

To your last two suggestions: there is no particular ordering for the mappings (for the heights I called them height.json and height2.json above for simplicity) and there can be many of them. Does this pose a problem to sequences (as the name would suggest)? For example, it would be inconvenient to assign each mapping a number (as opposed to a name), especially in the json files. Morphing between two mappings might be a nice effect later but is currently not desired. Also I am not sure if I want to keep all the possible mappings in memory all the time. Also the mappings (json files) are precomputed and will only change when the user selects another mapping, so without further changes no streams are involved.

csvurt commented 9 years ago

Hmm well this definitely shouldn't happen with the mesh/data format. Even so you should be using them instead of assets for this particular use case, they'll be more efficient at structure changes.

Could you attach a minimal example with just one <mesh> and the json files/dataflows?

At least now it's consistently broken, that's easier to debug :)

j4yk commented 9 years ago

You can download a zip file with the xhtml (also containing the dataflow and xflow operators) plus four json files, two for height, here: https://owncloud.hpi.de/public.php?service=files&t=329a895e45381cbb8137e81f35faf58f It also contains the JavaScript for the missing xflow.add #100.

You should be able to reproduce the following at the JavaScript console (I am using Chrome):

> document.getElementById("height-mapping").setAttribute("src", "minimal-example-height2.json")
undefined
> document.getElementById("height-mapping").setAttribute("src", "minimal-example-height1.json")
undefined
xml3d.js:1403 Mesh Error: Mesh does not have 'position' attribute.

(the needless index array is included because other boxes would have other 20 meaningful indices)

And thank you for the usage hints regarding assets. At some other point I messed things up in a way that my RAM was filled with the box data redundantly to the point of permanent page swapping and one attempt to fix it was to use instancing. I did not bother to change it back after I had found the real cause...

csvurt commented 9 years ago

Thanks a lot for the example! The above commit should fix the problem and will be in the 4.9 release. It should also stop the cubes from disappearing briefly after changing the src attribute.

It looks like our automated dev build isn't being published right now, I'll have to look into that. In the mean time you could add the fix to your local copy of xml3d.js since it's only one line. Let me know if it fixes the problem for you.

j4yk commented 9 years ago

Works like a charm now. Thank you very much! :-)

The cubes still disappear briefly when a loading a new file but no longer when switching back to an already visited one.