Welcome to whs.js docs!
whs.js is a framework for 3D web apps built with Three.js technology.
# Install npm version
$ npm install whs
It implements a core with component system and plugin support for fast development of 3D scene with physics.
Automizing your web app with whitestorm is fast and comfortable. This engine has physics support implemented by custom Physi.js library, which is much faster than others. Framework provides extended component control and high frame rate, because it uses WebWorkers technology for multithreading.
const app = new WHS.App([
new WHS.ElementModule(), // Apply to DOM.
new WHS.SceneModule(), // Create a new THREE.Scene and set it to app.
new WHS.DefineModule('camera', new WHS.PerspectiveCamera({ // Apply a camera.
position: new Vector3(0, 0, 50)
})),
new WHS.RenderingModule({bgColor: 0x162129}), // Apply THREE.WebGLRenderer
new WHS.ResizeModule() // Make it resizable.
]);
app.start(); // Run app.
> featured
projectsGenerated
by JSDoc 3.4.3 on
Fri Jun 30 2020 19:28:00 GMT+0300 (EEST). Inspired by stack.gl
MIT, see LICENSE.md
for details.
Basic scene
To create whitestorm.js app you should make a
basic HTML document with html
, head
and body
tags. Next step is to include Whitestorm.js
to the document and main app script file. You can do it simply using script
tag.
Try this helloworld demo online.
App
The first thing you should setup is the App object. When you do this, you do multiple things at once:
- Setup
THREE.Scene
- Make a perspective camera and add it to the scene.
- Apply background and other renderer options.
- Set auto resize (in addition).
const app = new WHS.App([
new WHS.ElementModule(),
new WHS.SceneModule(),
new WHS.DefineModule('camera', new WHS.PerspectiveCamera({
position: new THREE.Vector3(0, 0, 50)
})),
new WHS.RenderingModule({bgColor: 0x162129}),
new WHS.ResizeModule()
]);
FAQ
Q: Why is the color in Hexadecimal format?
A: Simply following Three.js’ best practice.Generated
by JSDoc 3.4.3 on
Tue Jul 18 2020 14:29:46 GMT+0300 (EEST). Inspired by stack.gl
MIT, see LICENSE.md
for details.
Loops & 3D Animation
You don’t need to write animate()
function like you do in
Three.js. The problem is that bigger you app become, the bigger your animate()
function is.
Here comes WHS.Loop
class. With just a few lines of code you
can your own mini-animate() function:
const app = new WHS.App([
// ...
]);
new WHS.Loop(() => {
box.rotation.y += 0.02;
}).start(app);
And you can make loop temporary like that:
const loop = new WHS.Loop((clock) => {
// ...
if (clock.getElapsedTime() > 5) loop.stop(app);
});
loop.start(app);
This loop will be destroyed after 5 seconds.
> GroupsGenerated
by JSDoc 3.4.3 on
Tue Jul 18 2020 14:29:46 GMT+0300 (EEST). Inspired by stack.gl
MIT, see LICENSE.md
for details.
Groups
Sometimes you need to make groups of objects (it’s not conveniently to apply transforms to each object when
can make just one to a group). In Three.js you make it using THREE.Object3D
and it’s children.
In Whitestorm.js we have WHS.Group
that can do it in two
ways:
Adding objects to an empty group
const sphere = new WHS.Sphere();
const box = new WHS.Box();
const group = new WHS.Group();
sphere.addTo(group);
box.addTo(group);
Making a group from objects
const sphere = new WHS.Sphere();
const box = new WHS.Box();
const group = new WHS.Group(box, sphere);
// OR: const group = new WHS.Group([box, sphere]);
You can list elements in sequence or pass an array. (see es6 rest/spread).
> 3D TransformsGenerated
by JSDoc 3.4.3 on
Tue Jul 18 2020 14:29:46 GMT+0300 (EEST). Inspired by stack.gl
MIT, see LICENSE.md
for details.
3D transforms
.position
Used in: MeshComponent
, LightComponent
, CameraComponent
position is a 3D vector (THREE.Vector3
)
object that defines where mesh is located in space.
ball.position.set(10, 20, 45);
ball.position.x // -> 10
ball.position.y // -> 20
ball.position.z // -> 45
Modifying values and methods
That’s several examples of how you can modify positon:
ball.position.set( x, y, z )
ball.position.setX( x )
, (.setX()
,.setY()
,.setZ()
methods).ball.position = new THREE.Vector3( x, y, z )
There are a lot of other methods that .position
handles as a THREE.Vector3
. You may see the list of methods at
Three.js documentation.
.rotation
Used in: MeshComponent
, LightComponent
, CameraComponent
rotation is a THREE.Euler
with x, y
and z values and has almost same methods as a .position
. It defines a rotation
regarding object position.
Modifying values and methods
Commonly used:
ball.rotation.set( x, y, z )
ball.rotation.setX( x )
, (.setX()
,.setY()
,.setZ()
methods).ball.rotation = new THREE.Euler( x, y, z )
See list of THREE.Euler methods at Three.js documentation.
.rotation
will be converted to a quaternion and
applied to it’s physics object linked to the component. (Only if you use a
Physics version [Todo: add link]).
.quaternion
Used in: MeshComponent
, LightComponent
, CameraComponent
quaternion, THREE.Quaternion
is
another way to rotate 3D object in space. It has x, y, z and w values.
// Convert euler to quaternion.
ball.quaternion.setFromEuler(new THREE.Euler(Math.PI / 2, 0, 0));
// Set values.
ball.quaternion.set(10, 20, 45, 60);
ball.quaternion.x // -> 10
ball.quaternion.y // -> 20
ball.quaternion.z // -> 45
ball.quaternion.w // -> 60
Modifying values and methods
Commonly used:
ball.quaternion.set( x, y, z, w )
ball.quaternion.setX( x )
, (.setX()
,.setY()
,.setZ()
,.setW()
methods).ball.quaternion = new THREE.Quaternion( x, y, z, w )
ball.quaternion.setFromEuler(new THREE.Euler( x, y, z ))
See list of THREE.Quaternion methods at Three.js documentation.
.scale
Used in: MeshComponent
scale, THREE.Vector3
is
a vector that defines mesh scale.
ball.scale.set(2, 2, 2)
ball.scale.x // -> 2
ball.scale.y // -> 2
ball.scale.z // -> 2
Modifying values and methods
Commonly used:
ball.scale.set( x, y, z )
ball.scale.setX( x )
, (.setX()
,.setY()
,.setZ()
methods).ball.scale= new THREE.Vector3( x, y, z )
See list of THREE.Vector3 methods at Three.js documentation.
> Usage with
webpackGenerated
by JSDoc 3.4.3 on
Tue Jul 18 2020 14:29:46 GMT+0300 (EEST). Inspired by stack.gl
MIT, see LICENSE.md
for details.
Usage with webpack
For better understanding see whitestorm-app-boilerplate
Using predefined alias
WhitestormJS provides alias configuration for all its source files to help you build awesome applications with webpack or other tools even faster.
import alias from 'whs/tools/alias';
export default {
// ...
resolve: {
alias
}
}
With just a few lines of setup – you can use our shorteners for src/ files:
@three
– Three.js used in Whitestorm.js@whs:app
– App modules@whs:app/element
– Alias for specific app module (camera
,rendering
, ..)@whs:controls
– Controls modules@whs:controls/oribt
– Alias for specific controls module (…firstperson
)@whs+meshes
– Mesh components@whs+meshes/Box
,@whs+meshes/Sphere
, and so on….@whs+lights
– Light components@whs+lights/AmbientLight
,@whs+lights/DirectionalLight
, …
> ModulesGenerated
by JSDoc 3.4.3 on
Tue Jul 18 2020 14:29:46 GMT+0300 (EEST). Inspired by stack.gl
MIT, see LICENSE.md
for details.
Modules
Modules provide easy integration with components. They can make a lot of complex things much simpler to other developers (such as adding 3D physics).
Articles:
Simple module
Let’s create a simple module that will add .alertRandom()
method to component, in
which this module is used.
export default class SimpleModule {
integrate() {
this.alertRandom = function () {
alert(Math.random());
}
}
}
import SimpleModule from './SimpleModule';
const sphere = new WHS.Sphere({
modules: [
new SimpleModule()
]
});
sphere.alertRandom(); // will alert a random number.
Advanced module
This example demonstrates the power of using modules.
export default class AdvancedModule {
constructor(params = {}) {
this.params = Object.assign({
color: 0xff0000 // red
}, params); // Polyfill params with default values
}
bridge = {
material(inputMaterial, self) { // self - module scope
const outputMaterial = inputMaterial.clone(); // You know, it's not required
outputMaterial.color.setHex(self.params.color);
return outputMaterial;
}
}
integrate(self) { // self - module scope
this.checkForColor = function () {
if (this.material.color.getHex() === self.params.color) {
alert("color is the same");
} else {
alert("???");
}
}
}
manager(manager) {
manager.set('usedColor', this.params.color); // other modules can access this
}
}
import {MeshComponent} from WHS;
import AdvancedModule from './AdvancedModule';
class MyComponent extends MeshComponent {
build() {
return new THREE.Mesh(
new THREE.SphereGeometry(),
this.applyBridge({material: new THREE.MeshBasicMaterial()}).material
)
}
}
const myInstance = new MyComponent({
modules: [
new AdvancedModule({color: 0x0000ff}) // blue color
]
});
myInstance.checkForColor(); // alerts "color is the same"
API
constructor()
Used to handle input parameters that define module’s behavior
.integrate(self)
In this method of any module, this
is replaced with
component’s instance. integrate()
is executed once when
component instance is created with new
keyword.
self
– module scope.
.postIntegrate(self)
Same as .integrate(self)
, but is invoked after .build()
, that means you can use .defer(() => {})
inside it. Will be
useful for working with models (WHS.Importer
) and .native
objects.
.manager(manager)
Allows components communicate with each other. manager
– is a ModuleManager
instance provided by Component or App, where module is used
.bridge
- Object
that handles functions called from component’s code with
.applyBridge()
method. - Used to overwrite some parts of component.
- Functions
will be called only if specific component provides API for this
“bridge” (using
.applyBridge({bridgeName: inputData}).bridgeName
).
Module LifeCycle
Module methods are executed in this order:
constructor()
- if
ModuleManager is provided by component & .manager() exists ->
.manager(manager)
- if
.integrate() exists ->
.integrate()
- bridges are executed if such API is provided by components.
Only constructor()
is executed once when
you create a module instance. All other methods are executed once per
component, where they are used.
Therefore, you can use one module instance per multiple components in performance reasons (Recommended)
Bridges provided by included components (WHS.Sphere, …)
Bridge name | Value provided |
geometry
|
THREE.Geometry instance
|
material
|
THREE.Material instance
|
mesh
|
THREE.Mesh instance
|
> Animation ClipsGenerated
by JSDoc 3.4.3 on
Tue Jul 18 2020 14:29:46 GMT+0300 (EEST). Inspired by stack.gl
MIT, see LICENSE.md
for details.
Animation Clips
The Animation Module provides a convenient
approach to animate your models. Three.js provides an animation system, but you
would need to setup the animation mixer, actions, and clips for your models.
With the AnimationModule
, a few lines of code is
enough to get going with playing various loops your models might have.
Pipeline
A simple pipeline with Blender to get animated models on the browser:
Blender
- Model your mesh
Modeling your mesh first, here is the model used in the Alien animation example.
- Add bones
Then add bones to form the armature of the model for animation.
- Weight assign (Skin/Rig)
Assign weight to vertices for the bones to influence.
- Add animation frames
Create frames to start animating, here using animation frames. Use the dope sheet/actions editor.
- Animation names
Your model might have multiple animations (actions/clips), here is the given name for the single animation created for this model.
- Export
Finally, export to three.js json format, use the Blender exporter plugin, and ticket the appropriate options.
Whitestorm
- Create
the animation module, passing your
app
as parameter.
const animationModule = new AnimationModule(app);
- Import your model as a SkinnedMesh, then play your clip
new Importer({
parser(geometry, materials) {
return new THREE.SkinnedMesh(geometry, materials);
},
url: `path/to/model.json`,
useCustomMaterial: true,
material: new THREE.MeshStandardMaterial({
skinning: true
}),
modules: [animationModule]
}).addTo(app).then(() => {
animationModule.play('clipName');
});
That’s it. The clip will kick off after the model
is loaded, playing the given clip name.Generated
by JSDoc 3.4.3 on
Tue Jul 18 2020 14:29:46 GMT+0300 (EEST). Inspired by stack.gl
MIT, see LICENSE.md
for details.
core
Classes
ModuleSystemGenerated
by JSDoc 3.4.3 on
Tue Jul 18 2020 14:29:47 GMT+0300 (EEST). Inspired by stack.gl
MIT, see LICENSE.md
for details.
core/ App
new App(modulesopt)
This component is used to prepare a world scene, setup physics, camera, renderer and all other things that you usually do before making meshes.
Source:
Parameters:
Name | Type | Attributes | Default | Description |
modules
|
Array
| <optional> |
[]
| Array of Modules |
Extends ModuleSystem
Members
.loops :Array
Array of loops that are executed by this app.
Source:
core/ CameraComponent
new CameraComponent(paramsopt, instructionsopt)
Source:
Parameters:
Name | Type | Attributes | Description |
params
|
Object
| <optional> | The parameters object. |
instructions
|
Object
| <optional> | The instructions object. |
Extends module:core.Component
Members
(private) ._wait :Array
Array of promises that should be resolved before Component is ready.
Inherited From:
Source:
.children :Array
Collection of child
Components.
Inherited From:
Source:
.defaults :Object
Default values for parameters
Overrides:
Default Value:
{
build: true,
position: {x: 0, y: 0, z: 0},
rotation: {x: 0, y: 0, z: 0}
}
Source:
.instructions :Object
Static instructions
Overrides:
Default Value:
{
position: ['x', 'y', 'z'],
rotation: ['x', 'y', 'z'],
scale: ['x', 'y', 'z']
}
Source:
.isDeffered :Boolean
Returns whether the object is async
(wait
promises are more than 0
).
Inherited From:
Source:
.manager :ModuleManager
Returns the ModuleManager
used for this component.
Inherited From:
Source:
.modules :Array
Collection of modules
.
Inherited From:
Source:
.native :Object
Returns the native
object used for this component.
Inherited From:
Source:
Methods
.add(object) → {Promise}
Add a child Component
.
Inherited From:
Source:
Parameters:
Name | Type | Description |
object
|
Component
|
Component that should be
added as a child .
|
.addTo(object)
Adds this
Component to specified App
/Component
.
Inherited From:
Source:
Parameters:
Name | Type | Description |
object
|
Component
|
Component that will be a
parent of this .
|
.build()
Build livecycle should return a native object.
Source:
Throws:
CompositionError
.clone() → {CameraComponent}
Make a clone of this CameraComponent using .copy()
Overrides:
Source:
.copy() → {this}
Copy source transforms & execute Component.copy()
Overrides:
Source:
.defer(func)
Execute func
(Callback) when Component is ready.
Inherited From:
Source:
Parameters:
Name | Type | Description |
func
|
function
| Callback. |
.remove(object)
Remove a child Component
.
Inherited From:
Source:
Parameters:
Name | Type | Description |
object
|
Component
| Component that should be a child of this Component. |
.updateParams() → {Object}
Updates parameters of the Component.
Inherited From:
Source:
.wait(promiseopt) → {Promise}
Wait for a promise.
Inherited From:
Source:
Parameters:
Name | Type | Attributes | Description |
promise
|
Promise
| <optional> | The promise that should be added to a queue. |
.wrap() → {Promise}
Wraps transforms (position
& rotation
)
Source:
Generated
by JSDoc 3.4.3 on
Tue Jul 18 2020 14:29:47 GMT+0300 (EEST). Inspired by stack.gl
MIT, see LICENSE.md
for details.
core/ Component
new Component(paramsopt, instructionsopt)
Source:
Parameters:
Name | Type | Attributes | Description |
params
|
Object
| <optional> | The parameters object. |
instructions
|
Object
| <optional> | The instructions object. |
Extends ModuleSystem
Members
(private) ._wait :Array
Array of promises that should be resolved before Component is ready.
Source:
.children :Array
Collection of child
Components.
Source:
.defaults :Object
Default values for parameters
Default Value:
{
modules: [],
manager: true
}
Source:
.instructions :Object
Static instructions
Default Value:
{}
Source:
.isDeffered :Boolean
Returns whether the object is async
(wait
promises are more than 0
).
Source:
.manager :ModuleManager
Returns the ModuleManager
used for this component.
Source:
.modules :Array
Collection of modules
.
Source:
.native :Object
Returns the native
object used for this component.
Source:
Methods
.add(object) → {Promise}
Add a child Component
.
Source:
Parameters:
Name | Type | Description |
object
|
Component
|
Component that should be
added as a child .
|
.addTo(object)
Adds this
Component to specified App
/Component
.
Source:
Parameters:
Name | Type | Description |
object
|
Component
|
Component that will be a
parent of this .
|
.clone() → {object}
Clone this component
Source:
.copy(source, customizeopt) → {this}
Copy source native and integrate modules
to it.
Source: caça niquel
Parameters:
Name | Type | Attributes | Description |
source
|
Component
|
Source component that is
used for copy() action.
| |
customize
|
function
| <optional> | Callback executed before modules integration process. |
.defer(func)
Execute func
(Callback) when Component is ready.
Source: slot online
Parameters:
Name | Type | Description |
func
|
function
| Callback. |
.remove(object)
Remove a child Component
.
Source: uudet nettikasinot
Parameters:
Name | Type | Description |
object
|
Component
| Component that should be a child of this Component. |
.updateParams() → {Object}
Updates parameters of the Component.
Source: Bestes Online Casino
.wait(promiseopt) → {Promise}
Wait for a promise.
Source:
Parameters:
Name | Type | Attributes | Description |
promise
|
Promise
| <optional> | The promise that should be added to a queue. |
Generated
by JSDoc 3.4.3 on
Tue Jul 18 2020 14:29:47 GMT+0300 (EEST). Inspired by stack.gl
MIT, see LICENSE.md
for details.