javascriptember.jsx3d

Rendering x3d indexedfacset with ember.js


I using x3d in an ember cli framework. In an older version of the ember framework everything runs well. I updated ember.js lately. After the ember.js update it is no problem to display idexedfaceset or indexedlineset in the x3d scene from the start of the ember application. But now there is a problem to add idexedfaceset or indexedlineset to the scene after the application is completely loaded. For example see the code below. If the display value is set to true by clicking a button the application throw an error:
Uncaught TypeError: Cannot read property 'getPoints' of null at x3dom.registerNodeType.defineClass.nodeChanged.nodeChanged (x3dom-full.js:4596)

I understand the error indicates that the coordinate tag is missing in this moment where x3d detect a node is added and try to render it. Afterwards I check the html code and the coordinate tag is where it should be. But the element isn't displayed in the x3d scene. It seems there is a short delay by adding the coordinate tag.
I know it is possible to display the element by using a jquery commad like $("#scene").append("..."). But I would like to use the ember behavior because i do a lot more like calculating positions and dimensions. I would be happy if someone could help to solve the problem. Thanks a lot.

//application.hbs
{{#if this.display}}
  <transform>
    <shape def="" ispickable="0" bboxsize="-1,-1,-1" bboxcenter="0,0,0" render="true">
      <appearance sorttype="auto" alphaclipthreshold="0.1">
        <material specularcolor="0,0,0" shininess="0.2" emissivecolor="0,0,0" ambientintensity="0.2" transparency="0.5" diffusecolor="0 0 1">
        </material>
      </appearance>
      <indexedfaceset ccw="true" colorpervertex="false" colorindex=" 0 0 0 0" coordindex="0 3 2 1 0" solid="true" usegeocache="true" lit="true" normalpervertex="true" normalupdatemode="fast" convex="true" >

        <coordinate point="-1 0 0, -1 1 0, 1 1 0, 1 0 0"></coordinate>

        <color color="0 0 1"></color>
      </indexedfaceset>
    </shape>
  </transform>
{{/if}} ```


Solution

  • Your latest changes finally allowed me to run the project. When researching your problem, I found a similar issue

    As far as I can tell, it has nothing to do with d3 or jquery and has everything to do with appending the indexed set before appending the coordinate using DOM functions which affect both d3 and jquery. Appending the coordinate to the indexed set and then appending the indexed set to the rest of the DOM should work fine.

    Another commenter noted

    For me, the node isn’t there yet, since I am creating DOM from JSON. The solution was to build the child node first, then add it to the parent, then add the parent. Before that, the code would die in the appendChild.

    The Ember rendering layer has changed a lot from Ember 1.x -> Ember 3.x. It seems to me that a change in the order in which nodes are built/appended to the DOM has caused this issue for you since x3dom is expecting one order and ember another.

    The first quick solution to your current issue here would be to avoid wrapping <transform> elements in {{#if}} blocks for hiding / showing since this removes / readds to the DOM in a way that x3dom is unaware of. Rather, control the visibility by using the x3dom render property

    <transform render="{{if this.display "true" "false"}}">
      <shape def="" ispickable="0" bboxsize="-1,-1,-1" bboxcenter="0,0,0" render="true">
        <appearance sorttype="auto" alphaclipthreshold="0.1">
          <material specularcolor="0,0,0" shininess="0.2" emissivecolor="0,0,0" ambientintensity="0.2" transparency="0.5" diffusecolor="0 0 1">
          </material>
        </appearance>
        <indexedfaceset ccw="true" colorpervertex="false" colorindex=" 0 0 0 0" coordindex="0 1 2 3 0" solid="true" usegeocache="true" lit="true" normalpervertex="true" normalupdatemode="fast" convex="true" >
    
            <coordinate point="-2 -2 0, 0 -2 0, 0 0 0, -2 0 0"></coordinate>
    
          <color color="0 0 1"></color>
        </indexedfaceset>
      </shape>
    </transform>
    

    Alternatively, you will need to also avoid wrapping the <transform> in {{#if}} and use the x3dom API directly via javascript in an @action.