# Polygon Streaming Web Player for Babylon.js

To run the example you first need to make sure you have [Node.js](https://nodejs.org) installed. Then run the following in a terminal:

```shell
npm install
npm run dev
```

It will open a browser window and display the model.

## Explanation of the Code

Import Babylon.js, glTF loader and the StreamController:

```javascript
import * as BABYLON from '@babylonjs/core/Legacy/legacy';
import '@babylonjs/loaders/glTF';
import { StreamController, loadWasmModule } from '@polygon-streaming/web-player-babylonjs';
```

Load Ammo.js. This is only required if you want to make use of the optional embedded collider in the model. Other physics plugins are not supported as Ammo.js is the only one that supports concave colliders. The Ammo.js physics plugin uses version 1 of the physics engine so you will need to add physics impostors to your meshes rather than physics aggregates or bodies.

```javascript
import ammoWasmJsUrl from './lib/ammo.wasm.js?url';
import ammoWasmWasmUrl from './lib/ammo.wasm.wasm?url';
import ammoJsUrl from './lib/ammo.js?url';

loadWasmModule('Ammo', ammoWasmJsUrl, ammoWasmWasmUrl, ammoJsUrl).then(ammoInstance => {
```

Instanciate the stream controller:

```javascript
const streamController = new StreamController(camera, engine, scene, cameraTarget, {
  cameraType: 'nonPlayer',
  triangleBudget: 3000000,
  mobileTriangleBudget: 1000000,
  closeUpDistance: 0.2,
  minimumDistance: 0.01,
  distanceFactor: 1.1,
  distanceType: 'boundingBoxCenter',
  maximumQuality: 15000,
  closeUpDistanceFactor: 5
  ammoInstance: ammoInstance
});
```

Add a streaming model, passing it a model URL and a TransformNode to act as a model parent.

```javascript
const modelParent = new BABYLON.TransformNode('Model parent', scene);
modelParent.position.set(0, 1, 0);

streamController.addModel('https://stream.viverse.com/demos/jet-engine-11m/', modelParent, {
  qualityPriority: 1,
  initialTrianglePercent: 0.1,
  castShadows: true,
  receiveShadows: true,
  castShadowsLightmap: true,
  forceDoubleSided: false,
  useAlpha: true,
  environmentMap: null,
  hashCode: ''
});
```

### Using Your Own Model

* Upload your 3D model to the [console](https://stream.viverse.com/console).
* To get the model URL go to the models section of the [console](https://stream.viverse.com/console/models) and click on the three dots next to your model and select "Copy asset ID".

Call the stream controller's update method in the render loop:

```javascript
engine.runRenderLoop(function () {
  scene.render();
  streamController.update();
});
```

## Stream Controller Parameters

* **camera** (Required): The camera used in the scene.
* **engine** (Required): The engine used in the scene.
* **scene** (Required): The scene object.
* **cameraTarget** (Required): The camera target which is a Vector3.
* **options** (Optional): All options are optional. The options are:
  * **cameraType**:  'nonPlayer' | 'player', default: 'nonPlayer'
    * **nonPlayer**: A camera that is not attached to a player e.g. a camera that orbits an object.
    * **player**: A camera that is attached to a player.
  * **triangleBudget**: number, default: 3000000. The maximum amount of triangles that you want to be in the scene at any single point.
  * **mobileTriangleBudget**: number, default: 1000000. The triangle budget used on a mobile device. If it is set to 0 it will use the non-mobile triangle budget.
  * **minimumDistance**: number, default: 0.01. The smallest possible distance to the camera.
  * **distanceFactor**: number, default: 1.1. Preference for nearby objects over objects further away. Values above one mean a preference for nearby objects. Values below one mean a preference for objects further away. One is neutral.
  * **distanceType**: 'boundingBoxCenter' | 'boundingBox', default: 'boundingBoxCenter'
    * **boundingBoxCenter**: Uses the center of the bounding box to caluclate the distance to the node.
    * **boundingBox**: Uses the bounding box corners and face centers to calulcate the distance to the node. 
  * **maximumQuality**: number, default: 15000. Stops improving geometry that exceeds the maximum quality. This can be used to stop far away objects from showing more detail which can be wasteful. Setting it to 0 means there is no maximum quality.
  * **closeUpDistance**: number, default: 3. The distance where it starts using close-up distance factor. Set it to 0 to not use close-up distance factor.
  * **closeUpDistanceFactor**: number, default: 5. The distance factor used when close-up to an object. Should be higher than the standard distance factor.
  * **ammoInstance**: object, default: null. The Ammo.js instance. Required if you want to make use of the embedded collider.

## Streaming Model Parameters

* **URL** (Required): URL of the XRG model. If it doesn't end with .xrg it will append model.xrg to the URL.
* **model parent** (Required): The scene object that the streaming model will be attached to.
* **options** (Optional): All options are optional. The options are:
  * **qualityPriority**: number, default: 1.  How much to prioritize the quality of this model relative to the quality of other models in the scene. This parameter does nothing if this is the only model in the scene.
  * **initialTrianglePercent**: number, default: 0.1. Percentage of triangle budget to initialize the model with.
  * **castShadows**: boolean, default: true. Whether the model should cast shadows.
  * **receiveShadows**: boolean, default: true. Whether the model should receive shadows.
  * **castShadowsLightmap**: boolean, default: true. Whether the model casts shadows when rendering lightmaps.
  * **forceDoubleSided**: boolean, default: false. Render the model double sided regardless of the setting in the model file.
  * **environmentMap**: CubeTexture, default: null. A cube map environment texture.
  * **hashCode**: string, default: ''. Hash code to validate streaming model.

