x3dom / x3dom

X3DOM. A framework for integrating and manipulating X3D scenes as HTML5/DOM elements.
http://x3dom.org
Other
815 stars 271 forks source link

Second group node in ProtoBody doesn't work fully #1176

Closed microaaron closed 2 years ago

microaaron commented 2 years ago

Example1: All shapes in the first group https://jsitor.com/RSdozbEw6 Example2: Put the blue box into the second group https://jsitor.com/-MsWz876g . The blue box disappeared. Example3: TimeSensor,PositionInterpolator,ROUTE in the second group https://jsitor.com/T7FlDL6IN. They still work.

Example2.x3d:

<X3D profile="Immersive" version="3.2">
  <Scene>    
    <ProtoDeclare name='testbox'>
      <ProtoInterface>
        <field name='translation' type='SFVec3f' accessType='inputOutput'></field>  
      </ProtoInterface>
      <ProtoBody> 
        <Group>
          <Transform DEF="box1">
            <IS>
              <connect nodeField="translation" protoField="translation"></connect>
            </IS>  
            <Shape>
              <Box size="1 1 1"></Box>
              <Appearance>
                <Material diffuseColor="0 1 0"></Material>
              </Appearance>
            </Shape>
          </Transform>
        </Group>
        <Group>  <!-- disappeared -->
          <Transform translation="2.5 0 0"> 
            <Transform DEF="box2"> 
              <Shape>
                <Box size="1 1 1"></Box>
                <Appearance>
                  <Material diffuseColor="0 0 1"></Material>
                </Appearance>
              </Shape>
            </Transform>
          </Transform>
        </Group>
      </ProtoBody>
    </ProtoDeclare>
  </Scene>
</X3D>

Example3.x3d:

<X3D profile="Immersive" version="3.2">
  <Scene>    
    <ProtoDeclare name='testbox'>
      <ProtoInterface>
        <field name='translation' type='SFVec3f' accessType='inputOutput'></field>  
      </ProtoInterface>
      <ProtoBody> 
        <Group>
          <Transform DEF="box1">
            <IS>
              <connect nodeField="translation" protoField="translation"></connect>
            </IS>  
            <Shape>
              <Box size="1 1 1"></Box>
              <Appearance>
                <Material diffuseColor="0 1 0"></Material>
              </Appearance>
            </Shape>
          </Transform>  
        </Group>
        <Group>  <!-- still work-->
      <TimeSensor DEF="Timer" cycleInterval="5" loop="true"></TimeSensor>
          <PositionInterpolator DEF="PI" key="0 0.25 0.5 0.75 1" keyValue="0 0 0, 0.5 0 0, 0 0 0, -0.5 0 0, 0 0 0"></PositionInterpolator>
      <ROUTE fromNode="Timer" fromField="fraction_changed" toNode="PI" toField="set_fraction"></ROUTE>
          <ROUTE fromNode="PI" fromField="value_changed" toNode="box1" toField="set_translation"></ROUTE>   
        </Group>
      </ProtoBody>
    </ProtoDeclare>
  </Scene>
</X3D>
andreasplesch commented 2 years ago

https://www.web3d.org/x3d/tooltips/X3dTooltips.html#ProtoBody explains that only the first root node is rendered. Since the ProtoInstance needs to be a single node in the scene graph, I think this is the only option. Do the examples work in other x3d browsers ?

The easy workaround is wrap all into a single group.

microaaron commented 2 years ago

BS Contact and view3dscene support TimeSensor,PositionInterpolator,ROUTE in the second group, but only BS Contact renders the second group. Anyway, I should abide by the rule. Thanks.

andreasplesch commented 2 years ago

Interesting. Perhaps BS Contact wraps everything internally into a single node, probably a group. But still uses the first node as the type.

brutzman commented 2 years ago

Yes, abiding by the rule is important. As author you can always start with a group. Worth noting is that the ability to "stash" additional nodes after the first node can provide valuable capabilities. As a simple example, if the first node is an IndexedFaceSet (or some other geometry node), then follow-on nodes within the ProtoBody can animate it. Then the entire ProtoInstance can appear within Shape, like any other geometry node. (Can't do that with a Group as topmost first node.) This gives authors great expressive power - and another reason why the "X" in X3D Graphics is Extensible.

andreasplesch commented 2 years ago

https://github.com/x3dom/x3dom/blob/83ce36310eda365a35ece8391e9a8c3f78800c38/src/nodes/Core/X3DNode.js#L82

shows how in x3dom additional (helper) nodes are wrapped internally in a Switch node. This Switch node does not have a parent, eg. is a root node which does not render. I think we determined at the time that this was a good solution to get the desired behaviour, and I cannot think of a better solution now. Perhaps castle or x_ite does it the same way.