x_ite icon indicating copy to clipboard operation
x_ite copied to clipboard

Filling up an empty scene with Javascript

Open Wagyx opened this issue 1 year ago • 8 comments

Hello there,

I have discovered your framework yesterday (I have been using 3JS for two years now) and I am struggling to make a scene from scratch. My HTML just has <x3d-canvas onclick="init()"></x3d-canvas> in the body and my script containing the init() is added after the body. My javascript is

function init() {
    const xBrowser = X3D.getBrowser();
    const scene = xBrowser.currentScene;
    const background = scene.createNode("Background");
    background.skyColor = [0, 0.3, 0.2];
    background.groundColor = [0.5, 0.8, 0.2];
}

This does not work, I get a black canvas. But if I use an x3d source file in the x3d-canvas <x3d-canvas src="/simple.x3d" onload="init()"> and use const background = scene.getNamedNode("Background"); instead then I get the dark green/light green canvas.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.3//EN" "http://www.web3d.org/specifications/x3d-3.3.dtd">
<X3D profile='Immersive' version='3.3' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='http://www.web3d.org/specifications/x3d-3.3.xsd'>
  <Scene>
    <Background DEF='Background'
        skyColor='0 0.5 1'/>
  </Scene>
</X3D>

I would like to add many other elements to the scene specified by the user (at some point) but I cannot even add a simple background. So what am I missing ?

Two bonuses questions, how do I loop over every Node with a specific tag like <Shape> ? Could I use DOM integration instead ?

Wagyx avatar May 02 '24 14:05 Wagyx

It is of course possible to get the Background node to be displayed. The Background node is, as well as Fog, NavigationInfo, and Viewpoint node an X3DBindableNode, which has a set_bind field. Assigning a true value to that field will bind this node and the isBound field will become true, and will send an event:

background.set_bind = true; // Will do the trick.
scene .rootNodes .push (background); // rootNodes is a MFNode field.

See also https://create3000.github.io/x_ite/components/environmentaleffects/background/.

Note that the skyColor and groundColor are MFColor fields, this means you should do to be compatible:

background.skyColor = new X3D .MFColor (new X3D .SFColor (0, 0.3, 0.2));
background.groundColor = new X3D .MFColor (new X3D .SFColor (0.5, 0.8, 0.2));

It is of course possible to assign pure Arrays, as you do, but this is not standard X3D, but will work.

To loop over the rootNodes you can do:

for (const node of scene .rootNodes)
{
   for (const type of node .getNodeType () .reversed ())
   {
      switch (type)
      {
          case X3D .X3DConstants .Background:
          {
              ....
              break;
          }
          default:
             continue;
      }

      break;
   }
}

See also https://create3000.github.io/x_ite/accessing-the-external-browser/#x3dconstants.

create3000 avatar May 02 '24 20:05 create3000

MF* fields are much like Arrays and have a corresponding SF* fields. Which can be assigned:

background.skyColor[0] = new X3D .SFColor (0.1, 0.2, 0.3);

https://create3000.github.io/x_ite/reference/field-services-and-objects/

create3000 avatar May 02 '24 20:05 create3000

I have updated the documentation to show a simple example, how to create nodes with JavaScript and add them to the scene-graph.

https://create3000.github.io/x_ite/accessing-the-external-browser/#usage

The first section shows the scene in declarative syntax, and below that there is the same scene created using pure JavaScript.

create3000 avatar May 02 '24 21:05 create3000

Thank you very much, a simple JavaScript example was exactly what I was missing. In the meantime, I managed to figure out how to add elements to the scene by looking into the various Parser codes and I made my own OFFParser, even adding it to the GoldenGate.Parser list to handle the src of the x3d-canvas seamlessly. I'll deal with InstancedShape today so I'll come back if I have any issue.

Wagyx avatar May 03 '24 08:05 Wagyx

You can continue to ask questions here if you like. I will be happy to help you.

create3000 avatar May 03 '24 09:05 create3000

Me again. What is the way in JavaScript to refer to another node with the "USE" keyword ? I see what it would look like from here https://create3000.github.io/x_ite/tutorials/naming-nodes/ but not what the proper JS syntax is.

Wagyx avatar May 03 '24 14:05 Wagyx

You do not have to do anything special, just add the node to another field, and that's it.

const shapeNode1 = scene .createNode ("Shape");
const shapeNode2 = scene .createNode ("Shape");
const boxNode = scene .createNode ("Box");

shapeNode1 .geometry = boxNode; // First use
shapeNode2 .geometry = boxNode; // Second use

When the scene is printed, proper DEF/USE statements are automatically generated.

create3000 avatar May 03 '24 15:05 create3000

So very simple ! It works :) Thank you. My project is 99% finished thanks to you.

Wagyx avatar May 03 '24 16:05 Wagyx