# regl-camera
A basic reusable "turntable" camera component for [regl](http://regl.party).  (Secretly just [spherical coordinates](https://en.wikipedia.org/wiki/Spherical_coordinate_system).)

## Example

```javascript
const regl = require('regl')()
const camera = require('regl-camera')(regl, {
  center: [0, 2.5, 0]
})

const bunny = require('bunny')
const normals = require('angle-normals')

const drawBunny = regl({
  frag: `
    precision mediump float;
    varying vec3 vnormal;
    void main () {
      gl_FragColor = vec4(abs(vnormal), 1.0);
    }`,
  vert: `
    precision mediump float;
    uniform mat4 projection, view;
    attribute vec3 position, normal;
    varying vec3 vnormal;
    void main () {
      vnormal = normal;
      gl_Position = projection * view * vec4(position, 1.0);
    }`,
  attributes: {
    position: bunny.positions,
    normal: normals(bunny.cells, bunny.positions)
  },
  elements: bunny.cells
})

regl.frame(() => {
  camera((state) => {
    if (!state.dirty) return;
    regl.clear({color: [0, 0, 0, 1]})
    drawBunny()
  })
})
```

## Install

```
npm i regl-camera
```

## API

### Constructor

#### `var camera = require('regl-camera')(regl[, options])`
`module.exports` of `regl-camera` is a constructor for the camera.  It takes the following arguments:

* `regl` is a handle to the regl instance
* `options` is an object with the following optional properties:
  + `center` which is the center of the camera
  + `theta` the theta angle for the camera
  + `phi` the phi angle for the camera
  + `distance` the distance from the camera eye to the center
  + `up` is the up vector for the camera
  + `fovy` is the field of view angle in y direction (defaults to `Math.PI / 4`)
  + `near` is the near clipping plane in z (defaults to `0.01`)
  + `far` is the far clipping plane in z (defaults to `1000.0`)
  + `mouse` set to `false` to turn off mouse events
  + `damping` multiplier for inertial damping (default 0.9). Set to 0 to disable inertia.
  + `noScroll` boolean flag to prevent mouse wheel from scrolling the whole window. Default is false.
  + `element` is an optional DOM element for mouse events (defaults to regl canvas element)
  + `rotationSpeed` the rotation interactions (default: `1`)
  + `zoomSpeed` the zoom interactions (default: `1`)
  + `renderOnDirty` boolean flag to control whether scene is only rendered when the camera state has changed. If true, render can be triggerd at any time by setting `camer.dirty = true`. If false, dirty state can still be detected and used through `context.dirty`.

### Command usage

#### `camera(block)`
`regl-camera` sets up an environment with the following variables in both the context and uniform blocks:

| Variable | Type | Description |
|----------|------|-------------|
| `view`   | `mat4` | The view matrix for the camera |
| `projection` | `mat4` | The projection matrix for the camera |
| `center` | `vec3` | The center of the camera |
| `eye` | `vec3` | The eye coordinates of the camera |
| `up` | `vec3` | The up vector for the camera matrix |
| `theta` | `float` | Latitude angle parameter in radians |
| `phi` | `float` | Longitude angle parameter in radians |
| `distance` | `float` | Distance from camera to center of objective |
| `dirty` | `boolean` | Flag set to true when camera state has changed |

**Note**
These properties can also be accessed and modified directly by accessing the object, though at the moment you will need to manually set `camera.dirty = true` if relying upon `renderOnDirty`

## License
(c) 2016 Mikola Lysenko. MIT License
