Skip to content

Commit

Permalink
Added orbit camera control
Browse files Browse the repository at this point in the history
  • Loading branch information
jnsmalm committed Apr 19, 2020
1 parent 6b7d241 commit 162cf70
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 11 deletions.
12 changes: 7 additions & 5 deletions src/camera.ts → src/camera/camera.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as PIXI from "pixi.js"

import { Container3D } from "./container"
import { Matrix4 } from "./math/matrix4"
import { Vector4 } from "./math/vector4"
import { MatrixComponent } from "./matrix/matrix-component"
import { Container3D } from "../container"
import { Matrix4 } from "../math/matrix4"
import { Vector4 } from "../math/vector4"
import { MatrixComponent } from "../matrix/matrix-component"

const mat4 = Matrix4.create()
const vec4 = Vector4.create()
Expand Down Expand Up @@ -40,7 +40,9 @@ export class Camera3D extends Container3D {
// renderer aspect ratio has changed).
this._id++
}
this.transform.updateTransform()
if (!this.parent) {
this.transform.updateTransform()
}
})
if (!Camera3D.main) {
Camera3D.main = this
Expand Down
68 changes: 68 additions & 0 deletions src/camera/orbit-camera.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { Quaternion } from "../math/quaternion"
import { Camera3D } from "./camera"
import { Matrix3 } from "../math/matrix3"
import { Matrix4 } from "../math/matrix4"
import { Vector3 } from "../math/vector3"
import { MatrixPool } from "../math/matrix-pool"

/**
* Allows the user to control the camera by orbiting around the target.
*/
export class OrbitCameraControl {
private _rotation = Quaternion.create()
private _distance = 5

/** Allows the camera to be controlled. */
allowControl = true

constructor(canvas: HTMLCanvasElement, public camera = Camera3D.main) {
canvas.addEventListener("mousewheel", (event: Event) => {
if (this.allowControl) {
this.distance -= (<WheelEvent>event).deltaY * 0.01
event.preventDefault()
}
})
canvas.addEventListener("mousemove", (event) => {
if (this.allowControl && event.buttons === 1) {
this.updateOrbitBy(-event.movementX * 0.01, -event.movementY * 0.01)
}
})
}

get distance() {
return this._distance
}

/**
* Get or sets the distance (in units) between camera and the target.
*/
set distance(value: number) {
this._distance = value
this.updateOrbitBy(0, 0)
}

/**
* Updates the orbit position by the specified x-axis and y-axis.
* @param x Value for the x-axis.
* @param y Value for the y-axis.
*/
updateOrbitBy(x: number, y: number) {
MatrixPool.scope(() => {
Quaternion.rotateY(this._rotation, x, this._rotation)
Quaternion.rotateX(this._rotation, y, this._rotation)

let pos = Vector3.transformQuat(
Vector3.from({ x: 0, y: 0, z: this._distance }), this._rotation)
let up = Vector3.from({ x: 0, y: 1, z: 0 })
let forward = Vector3.normalize(pos)
let target = Vector3.from({ x: 0, y: 0, z: 0 })
let rot = Quaternion.normalize(
Quaternion.fromMat3(
Matrix3.fromMat4(
Matrix4.targetTo(target, forward, up))))

this.camera.rotationQuaternion.set(rot[0], rot[1], rot[2], rot[3])
this.camera.position.set(pos[0], pos[1], pos[2])
})
}
}
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ export { ObservablePoint3D } from "./point"
export { ObservableQuaternion } from "./quaternion"
export { Transform3D } from "./transform"
export { Container3D } from "./container"
export { Camera3D } from "./camera"
export { Camera3D } from "./camera/camera"
export { OrbitCameraControl } from "./camera/orbit-camera"
export { Mesh3D } from "./mesh/mesh"
export { Model3D } from "./model"
export { LightingEnvironment } from "./lighting/lighting-environment"
Expand Down
2 changes: 1 addition & 1 deletion src/math/matrix4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export namespace Matrix4 {
}
})

export function targetTo(eye: vec3, target: mat4, up: vec3, out?: mat4) {
export function targetTo(eye: vec3, target: vec3, up: vec3, out?: mat4) {
return mat4.targetTo(out || create(), eye, target, up)
}

Expand Down
2 changes: 1 addition & 1 deletion src/pbr/pbr-material.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { PhysicallyBasedShaderFeature } from "./pbr-feature"
import { PhysicallyBasedShader } from "./pbr-shader"
import { Material } from "../material"
import { MeshVertexData } from "../mesh/mesh-vertex"
import { Camera3D } from "../camera"
import { Camera3D } from "../camera/camera"
import { glTFMaterial } from "../gltf/gltf-material"
import { LightingEnvironment } from "../lighting/lighting-environment"
import { Mesh3D } from "../mesh/mesh"
Expand Down
2 changes: 1 addition & 1 deletion src/picking/color-material.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as PIXI from "pixi.js"

import { Camera3D } from "../camera"
import { Camera3D } from "../camera/camera"
import { Material, MaterialShaderAttribute } from "../material"
import { Mesh3D } from "../mesh/mesh"

Expand Down
4 changes: 2 additions & 2 deletions src/skybox/skybox-material.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as PIXI from "pixi.js"

import { Camera3D } from "../camera"
import { Material, MaterialShaderAttribute, MaterialFactory } from "../material"
import { Camera3D } from "../camera/camera"
import { Mesh3D } from "../mesh/mesh"
import { Material, MaterialShaderAttribute, MaterialFactory } from "../material"

const vert: string = require("./shader/skybox.vert").default
const frag: string = require("./shader/skybox.frag").default
Expand Down

0 comments on commit 162cf70

Please sign in to comment.