# Basics of Scene Construction

## Starter document

To begin we'll use the result of the Getting Started guide as a starting point:

```<!DOCTYPE html>
<html>
<title>My Project</title>
<script src="path_to/CubicVR.js" type="text/javascript"></script>
<script type='text/javascript'>
function webGLStart(gl,canvas) {
// perform any initialisation here.

// Start our main drawing loop, it provides a timer and the gl context as parameters
CubicVR.MainLoop(function(timer, gl) {
// perform any per-frame operations here
// perform any drawing operations here
});
}
</script>
</html>```

## Construct a Scene

To begin we take the `webGLStart(...)` function and instantiate a scene with a constructor to describe it's contents in the init section. For this example, we'll create one with a box at `[x, y, z]` of `[0,0,0]` and a point light at `[1.0, 1.5, -2.0]` with the camera at `[1.0, 1.0, -1.0]` which is looking at `[0.0, 0.0, 0.0]`.

Note that `x,y,z` coordinates are always an array of 3 floats where `x` is `[0]`, `y` is `[1]` and `z` is `[2]` respectively. The coordinate system in CubicVR.js is right-handed with positive X facing right, positive Y facing up and positive Z facing out of the screen when viewing X/Y.

We add the init code before the MainLoop since it only needs to be done one time:

```function webGLStart(gl,canvas) {
// init and setup here
var scene = new CubicVR.Scene({
camera: {
name: "the_camera",
fov: 60.0,
position: [1.0, 1.0, -1.0],
lookat: [0.0, 0.0, 0.0],
width: canvas.width,
height: canvas.height,
},
light: {
name: "the_light",
type: "point",
position: [1.0, 1.5, -2.0]
},
sceneObject: {
name: "the_box",
position: [0.0, 0.0, 0.0],
mesh: {
primitive: {
type: "box",
size: 1.0
},
compile: true
}
}
});

// Add the default scene camera to the resize list to update on browser resize

// Start our main drawing loop, it provides a timer and the gl context as parameters
CubicVR.MainLoop(function(timer, gl) {
// perform any per-frame operations here
// perform any drawing operations here
scene.render();
});
}
```

And with just that, we now have a simple grey point-lit cube on a black backdrop:

Next we'll break down the scene constructor and see what happened there.

## Breaking it down

The first portion of the Scene constructor specifies a Camera. The camera is named `"the_camera"` and has a field of view of `60` degrees, a position of `[1.0, 1.0, -1.0]` and a target of `[0, 0, 0]`. We also supply the width and height of the canvas so that the aspect ratio can be calculated appropriately.

The first camera supplied will become the default camera for the scene until you choose to change it by passing a camera or camera name to `scene.setCamera("another_camera")`.

You can set the aspect of your choosing with `CubicVR.setFixedAspect(aspect)` where `aspect` is typically `view_width/view_height` to fix the aspect to that of a specific resolution. Note this must be done before the call to `CubicVR.start(...)` to create an appropriately sized canvas unless you force a browser resize event, using `CubicVR.init()` may be preferable in that case.

```    // init and setup here
var scene = new CubicVR.Scene({
camera: {
name: "the_camera",
fov: 60.0,
position: [1.0, 1.0, -1.0],
lookat: [0.0, 0.0, 0.0],
width: canvas.width,
height: canvas.height,
}, ```

Next item in the constructor is the Light. It's a simple point light named `"the_light"` and is situated at position `[1.0, 1.5, -2.0]`. By default the light will be a soft white with a maximum radius (distance) of `10`.

```        light: {
name: "the_light",
type: "point",
position: [1.0, 1.5, -2.0]
},```

Next in the constructor is the cube, which is actually a recursive construction where the `CubicVR.SceneObject` will pass the nested constructor along to a new `CubicVR.Mesh` to build the requested primitive. The box is named `"the_box"` and is positioned at `[0.0, 0.0, 0.0]` (which you'll note is also the camera's target).

The Mesh is recursively instructed to construct a primitive of type `"box"` (or cube) with a size of `1.0`. Finally the mesh is told to `compile: true` the resulting primitives as we're finished constructing the mesh and need to compile and upload it to the GPU before rendering.

```        sceneObject: {
name: "the_box",
position: [0.0, 0.0, 0.0],
mesh: {
primitive: {
type: "box",
size: 1.0
},
compile: true
}
}
});```

Next are additions to MainLoop and an additional init for the resize of the Camera.

The addResizeable(object) command simply adds any object passed with a `resize(x,y)` member function to an internal list that will be updated any time the browser dimensions change. This prevents the aspect from skewing when using the default full-screen set-up (without fixed aspect).

```    // Add the default scene camera to the resize list to update on browser resize
```

Finally we need to add the command to actually draw something to the canvas. To do that simply add the scene's `render()` call to the inner MainLoop function.

```    // Start our main drawing loop, it provides a timer and the gl context as parameters
CubicVR.MainLoop(function(timer, gl) {
// perform any per-frame operations here
// perform any drawing operations here
scene.render();
});
```

## Breaking it down even more

The example above used nested constructors to build the scene and CubicVR.js expands the structure for you. But to get to the root of what's happening it's best explained by unrolling the construction to show the individual parts.

Here's the previous example unrolled:

```        function webGLStart(gl,canvas) {
// init and setup here
// Create the Camera
var camera = new CubicVR.Camera({
name: "the_camera",
fov: 60.0,
position: [1.0,1.0,-1.0],
lookat: [0.0,0.0,0.0],
width: canvas.width,
height: canvas.height
});

// Create the Light
var light = new CubicVR.Light({
name: "the_light",
type: "point",
position: [1.0,1.5,-2.0]
});

// Create the Box Mesh
var boxMesh = new CubicVR.Mesh({
primitive: {
type: "box",
size: 1.0
},
compile: true
});

// Create the SceneObject
var sceneObject = new CubicVR.SceneObject({
name: "the_box",
position: [0.0,0.0,0.0],
mesh: boxMesh
});

// Create the Scene
var scene = new CubicVR.Scene();

// Bind the Camera, Light and SceneObject to the scene
// Type will be recognized, alternatively you can use
// scene.bindCamera(), scene.bindSceneObject(),
// and scene.bindLight()
scene.bind(camera);
scene.bind(light);
scene.bind(sceneObject);

// Add the default scene camera to the resize list to update on browser resize

// Start our main drawing loop, it provides a timer and the gl context as parameters
CubicVR.MainLoop(function(timer, gl) {
// perform any per-frame operations here
// perform any drawing operations here
scene.render();
});
}```

## Adding more to the Scene

Up to this point the examples have only shown a single Light, Camera, SceneObject and Mesh. You can probably guess how it's possible to bind multiple items via multiple .bind() calls, but it's also easily done in the Scene constructor as well.

Here's an example of using two of each item in the constructor:

```    function webGLStart(gl,canvas) {
// init and setup here

// Here we take the mesh out of the construction, since it's
// preferrable to only have one copy of the mesh to save
// memory
var boxMesh = new CubicVR.Mesh({
primitive: {
type: "box",
size: 1.0
},
compile: true
});

// Add two of each type of item.  Basically, you can use the plural
// property (not required) and specify an array of constructors for each.
var scene = new CubicVR.Scene({
cameras: [{ // camera array start
name: "the_camera",
fov: 60.0,
position: [1.0,1.0,-1.0],
lookat: [0.0,0.0,0.0],
width: canvas.width,
height: canvas.height,
},{ // second camera in array
name: "another_camera",
fov: 90.0,
position: [-1.0,3.0,2.0],
lookat: [0.0,0.0,0.0],
width: canvas.width,
height: canvas.height,
}], // camera array end
lights: [{
name: "the_light",
type: "point",
position: [1.0,1.5,-2.0]
},{ // alter the diffuse color and pos
name: "another_light",
type: "point",
diffuse: [0.0,0.2,0.8],
position: [-2.0,1.5,-2.0]
}],
sceneObjects: [{
name: "the_box",
position: [0.0,0.0,0.0],
mesh: boxMesh
},{ // change up the position and scale a bit
name: "another_box",
position: [0.0,1.0,1.5],
scale: [1.0,2.0,1.0],
mesh: boxMesh
}],
});

// Add both cameras to the resize list so they're updated when needed

// By default the scene will use the first camera, you can change it at runtime.
// Uncomment the line below to switch to the second camera:
// scene.setCamera("another_camera");

// Start our main drawing loop, it provides a timer and the gl context as parameters
CubicVR.MainLoop(function(timer, gl) {
// perform any per-frame operations here
// perform any drawing operations here
scene.render();
});
}```

And the resulting render:

## Making it external

Any of the constructors shown so far can be turned into shared resources easily by placing them in an external file. Most CubicVR.js constructors support passing a string to an external resource, or if prefixed with a # character you can reference it from an internal document script element id.

For this example we'll de-construct the constructor into files as much as possible; it would also be acceptable to place the entire scene constructor in just `scene.json`.

Here's what the first example scene might look like if you moved it into external json files:

The `camera.json` file:

```{
name: "the_camera",
fov: 60.0,
position: [1.0,1.0,-1.0],
lookat: [0.0,0.0,0.0]
}```

The `light.json` file:

```{
name: "the_light",
type: "point",
position: [1.0,1.5,-2.0]
}```

The box mesh `mesh.json` file:

```{
primitive: {
type: "box",
size: 1.0
},
compile: true
}```

The `sceneObject.json` file:

```{
name: "the_box",
position: [0.0,0.0,0.0],
mesh: "mesh.json"
}```

Finally, the `scene.json` file:

```{
camera: "camera.json",
light: "light.json",
sceneObject: "sceneObject.json"
}```

Take note that external files can reference other external files without issue, this also means you can mix XML and JSON resources if desired.

After externalising the resources the webGLStart() function can be greatly simplified. Also note that since canvas dimensions aren't passed it needs to be handled with a `resize()` call to the scene or camera:

```function webGLStart(gl,canvas) {
// init and setup here
var scene = new CubicVR.Scene("scene.json");

// Ensure our camera starts out the correct size,
// since the json file didn't include canvas dimensions!
scene.resize(canvas.width, canvas.height);

// Add the default scene camera to the resize list to update on browser resize

// Start our main drawing loop, it provides a timer and the gl context as parameters
CubicVR.MainLoop(function(timer, gl) {
// perform any per-frame operations here
// perform any drawing operations here
scene.render();
});
}```

If you want to specify multiple items per file just create an array as you would for the constructor normally:

File `sceneObjects.json`, load in place of `sceneObject.json` in `scene.json`:

```[{
name: "the_box",
position: [0.0,0.0,0.0],
mesh: "mesh.json"
},{
name: "another_box",
position: [0.0,1.0,1.5],
scale: [1.0,2.0,1.0],
mesh: "mesh.json"
}]```

It's also worth noting in this case, that the `mesh.json` file duplication is recognized and optimally only a single instance of the mesh will be loaded and used. If the mesh constructor is repeated twice without externalising (or by creating a shared variable such as `boxMesh`) it will create two separate instances and consume twice as much memory.

## Using XML equivalent resources

For every constructor you can use a `.js` or `.json` resource; but you can also construct an identical constructor in XML. CubicVR.js converts all XML files into JSON before using them internally. It also can parse XML within a worker without the need for DOM, or from a Javascript string containing XML.

Note that the XML parser via string or within a worker is limited, and may not support all XML files. It is recommended you convert your file to the BadgerFish-JSON format first if using workers. BadgerFish-JSON is also used internally for all XML parsing and can be used directly instead of the XML file

Here's the previous external example, with some JSON files exchanged for XML files. This example also includes two SceneObjects to represent how arrays are represented and references to both JSON and XML files to show how they can be inter-mixed:

Here's the `mesh.xml` file:

```<mesh>
<primitive>
<type>box</type>
<size>1.0</size>
</primitive>
<compile>true</compile>
</mesh>```

The `sceneObjects.xml` file, showing array usage, note the root element can be anything you like:

```<mySceneObjects>
<sceneObject>
<name>the_box</name>
<position>0.0,0.0,0.0</position>
<mesh>mesh.xml</mesh>
</sceneObject>
<sceneObject>
<name>another_box</name>
<position>0.0,1.0,1.5</position>
<scale>1.0,2.0,1.0</scale>
<mesh>mesh.xml</mesh>
</sceneObject>
</mySceneObjects>```

And the `scene.xml` file, utilising previous JSON parts as well:

```<scene>
<camera>camera.json</camera>
<light>light.json</light>
<sceneObjects>sceneObjects.xml</sceneObjects>
</scene>```

And the only change required for webGLStart() is:

```    function webGLStart(gl,canvas) {
// init and setup here
var scene = new CubicVR.Scene("scene.xml");
...```

## Moving on

Now that the basics of procedural scene construction are handled you're ready to add some life to the scene via lighting, materials and textures.

To continue check out: Materials and Lighting.

Something went wrong with that request. Please try again.