Looking at Custom Camera Inputs

Photo by bruce mars on Unsplash
Photo by Bryan Natanael on Unsplash
// Examples of removing various camera inputs
// Removing FreeCamera Keyboard
camera.inputs.removeByType("FreeCameraKeyboardMoveInput");
// Removing ArcRotateCamera Keyboard
camera.inputs.removeByType("ArcRotateCameraKeyboardMoveInput");
// Removing FreeCamera Mouse
camera.inputs.removeByType("FreeCameraMouseInput");
// Removing ArcRotateCamera Pointers (combined Mouse/Touch)
camera.inputs.removeByType("ArcRotateCameraPointersInput");
Photo by Glenn Carstens-Peters on Unsplash

Components of a Custom Input Object

In order to define a Custom Input object, you will need to define any needed variables (keys, sensibility, etc.) and the following functions:

// Javascript
ExamplePointerInput.prototype.getClassName() = function () {
return "ExamplePointerInput";
};
// Typescript
public getClassName(): string {
return "ExamplePointerInput";
}
// Javascript
ExamplePointersInput.prototype.getSimpleName() = function () {
return “pointer”;
};
// Typescript
public getSimpleName(): string {
return "pointer";
};

Breakdown of Example: Chessboard Demo

So a while back I created a demo that shows a chessboard with some objects that can be interacted with. Inside of this demo, I had to get creative with the keyboard inputs because the standard ArcRotateCamera’s keyboard controls didn’t do everything that I needed them to. First, let’s look at the variables that I created for my Custom Input class (Note: this code will be in Javascript)

var ArcRotateCameraKeyboardPanInput = function () {
this._keys = [];

this.keysLeft = [37];
this.keysRight = [39];
this.keysUp = [38];
this.keysDown = [40];
};
ArcRotateCameraKeyboardPanInput.prototype.activeMove = true;
ArcRotateCameraKeyboardPanInput.prototype.activeRotate = false;
ArcRotateCameraKeyboardPanInput.prototype.getClassName = function () {
return "ArcRotateCameraKeyboardPanInput";
};
ArcRotateCameraKeyboardPanInput.prototype.getSimpleName = function () {
return "KeyboardPan";
};
ArcRotateCameraKeyboardPanInput.prototype.attachControl = function (noPreventDefault) {
var _this = this;
var engine = this.camera.getEngine();
var element = engine.getInputElement();
if (!this._onKeyDown) {
element.tabIndex = 1;
this._onKeyDown = function (evt) {
if (_this.keysLeft.indexOf(evt.keyCode) !== -1 ||
_this.keysRight.indexOf(evt.keyCode) !== -1 ||
_this.keysUp.indexOf(evt.keyCode) !== -1 ||
_this.keysDown.indexOf(evt.keyCode) !== -1) {
var index = _this._keys.indexOf(evt.keyCode);
if (index === -1) {
_this._keys.push(evt.keyCode);
}
if (!noPreventDefault) {
evt.preventDefault();
}
}
};
this._onKeyUp = function (evt) {
if (_this.keysLeft.indexOf(evt.keyCode) !== -1 ||
_this.keysRight.indexOf(evt.keyCode) !== -1 ||
_this.keysUp.indexOf(evt.keyCode) !== -1 ||
_this.keysDown.indexOf(evt.keyCode) !== -1) {
var index = _this._keys.indexOf(evt.keyCode);
if (index >= 0) {
_this._keys.splice(index, 1);
}
if (!noPreventDefault) {
evt.preventDefault();
}
}
};
element.addEventListener("keydown", this._onKeyDown, false);
element.addEventListener("keyup", this._onKeyUp, false);
BABYLON.Tools.RegisterTopRootEvents(canvas, [
{ name: "blur", handler: this._onLostFocus }
]);
}
};
ArcRotateCameraKeyboardPanInput.prototype.checkInputs = function () {
if (this._onKeyDown) {
if (this.activeMove) {
var speed = 2 * camera._computeLocalCameraSpeed();
let transformMatrix = BABYLON.Matrix.Zero();
let localDirection = BABYLON.Vector3.Zero();
let transformedDirection = BABYLON.Vector3.Zero();
for (var index = 0; index < this._keys.length; index++) {
var keyCode = this._keys[index];
if (this.keysLeft.indexOf(keyCode) !== -1) {
localDirection.copyFromFloats(-speed, 0, 0);
}
else if (this.keysRight.indexOf(keyCode) !== -1) {
localDirection.copyFromFloats(speed, 0, 0);
}
else if (this.keysUp.indexOf(keyCode) !== -1) {
localDirection.copyFromFloats(0, speed, 0);
}
else if (this.keysDown.indexOf(keyCode) !== -1) {
localDirection.copyFromFloats(0, -speed, 0);
}
camera.getViewMatrix().invertToRef(transformMatrix);
BABYLON.Vector3.TransformNormalToRef(localDirection, transformMatrix, transformedDirection);
camera.position.addInPlace(transformedDirection);
camera.target.addInPlace(transformedDirection);
}
}
else if (this.activeRotate) {
for (var index = 0; index < this._keys.length; index++) {
var keyCode = this._keys[index];
if (this.keysLeft.indexOf(keyCode) !== -1) {
camera.inertialAlphaOffset -= 3 / 1000;
}
else if (this.keysRight.indexOf(keyCode) !== -1) {
camera.inertialAlphaOffset -= -3 / 1000;
}
else if (this.keysUp.indexOf(keyCode) !== -1) {
camera.inertialBetaOffset -= 3 / 1000;
}
else if (this.keysDown.indexOf(keyCode) !== -1) {
camera.inertialBetaOffset -= -3 / 1000;
}
}
}
}
};
ArcRotateCameraKeyboardPanInput.prototype.detachControl = function () {
if (this._onKeyDown) {
var engine = this.camera.getEngine();
var element = engine.getInputElement();
element.removeEventListener("keydown", this._onKeyDown);
element.removeEventListener("keyup", this._onKeyUp);
BABYLON.Tools.UnregisterTopRootEvents(canvas, [
{ name: "blur", handler: this._onLostFocus }
]);
this._keys = [];
this._onKeyDown = null;
this._onKeyUp = null;
}
};

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Babylon.js

Babylon.js

1.4K Followers

Babylon.js: Powerful, Beautiful, Simple, Open — Web-Based 3D At Its Best. https://www.babylonjs.com/