diff --git a/types/three/test/docs/scenes/bones_browser.ts b/types/three/test/docs/scenes/bones_browser.ts
index c04a788cde..116af826d8 100644
--- a/types/three/test/docs/scenes/bones_browser.ts
+++ b/types/three/test/docs/scenes/bones_browser.ts
@@ -42,7 +42,7 @@
initBones();
}
function createGeometry(sizing: any) {
- var geometry = new THREE.CylinderGeometry(
+ var geometry = new THREE.CylinderBufferGeometry(
5, // radiusTop
5, // radiusBottom
sizing.height, // height
@@ -50,14 +50,29 @@
sizing.segmentCount * 3, // heightSegments
true // openEnded
);
- for (var i = 0; i < geometry.vertices.length; i++) {
- var vertex = geometry.vertices[i];
+
+ var position = geometry.attributes.position as THREE.BufferAttribute;
+
+ var vertex = new THREE.Vector3();
+
+ var skinIndices = [];
+ var skinWeights = [];
+
+ for (var i = 0; i < position.count; i++) {
+ vertex.fromBufferAttribute(position, i);
+
var y = (vertex.y + sizing.halfHeight);
+
var skinIndex = Math.floor(y / sizing.segmentHeight);
var skinWeight = (y % sizing.segmentHeight) / sizing.segmentHeight;
- geometry.skinIndices.push(new THREE.Vector4(skinIndex, skinIndex + 1, 0, 0));
- geometry.skinWeights.push(new THREE.Vector4(1 - skinWeight, skinWeight, 0, 0));
+
+ skinIndices.push(skinIndex, skinIndex + 1, 0, 0);
+ skinWeights.push(1 - skinWeight, skinWeight, 0, 0);
}
+
+ geometry.addAttribute('skinIndex', new THREE.Uint16BufferAttribute(skinIndices, 4));
+ geometry.addAttribute('skinWeight', new THREE.Float32BufferAttribute(skinWeights, 4));
+
return geometry;
}
function createBones(sizing: any) {
@@ -74,7 +89,7 @@
}
return bones;
}
- function createMesh(geometry: THREE.Geometry, bones: THREE.Bone[]) {
+ function createMesh(geometry: THREE.BufferGeometry, bones: THREE.Bone[]) {
var material = new THREE.MeshPhongMaterial({
skinning: true,
color: 0x156289,
diff --git a/types/three/test/references.ts b/types/three/test/references.ts
index e2068d68a5..d966799943 100644
--- a/types/three/test/references.ts
+++ b/types/three/test/references.ts
@@ -2,3 +2,4 @@
///
///
+///
diff --git a/types/three/test/webgl/webgl_animation_skinning_morph.ts b/types/three/test/webgl/webgl_animation_skinning_morph.ts
index 835d7a6ea5..e9129084ba 100644
--- a/types/three/test/webgl/webgl_animation_skinning_morph.ts
+++ b/types/three/test/webgl/webgl_animation_skinning_morph.ts
@@ -1,228 +1,209 @@
-// https://github.com/mrdoob/three.js/blob/master/examples/webgl_sprites.html
+// https://github.com/mrdoob/three.js/blob/master/examples/webgl_animation_skinning_morph.html
() => {
// ------- variable definitions that does not exist in the original code. These are for typescript.
+ interface WEBGL {
+ isWebGLAvailable(): boolean;
+
+ isWebGL2Available(): boolean;
+
+ getWebGLErrorMessage(): HTMLDivElement;
+
+ getWebGL2ErrorMessage(): HTMLDivElement;
+
+ getErrorMessage(version: 1 | 2): HTMLDivElement;
+ }
+
+ var WEBGL: WEBGL;
// -------
- var SCREEN_WIDTH = window.innerWidth;
- var SCREEN_HEIGHT = window.innerHeight;
- var FLOOR = -250;
-
- var container: HTMLElement;
+ if (WEBGL.isWebGLAvailable() === false) {
+ document.body.appendChild(WEBGL.getWebGLErrorMessage());
+ }
+ var container: HTMLElement
var stats: Stats;
+ var clock: THREE.Clock;
+ var gui: dat.GUI;
+ var mixer: THREE.AnimationMixer;
+ var actions: { [name: string]: THREE.AnimationAction };
+ var activeAction: THREE.AnimationAction;
+ var previousAction: THREE.AnimationAction;
+
var camera: THREE.PerspectiveCamera;
var scene: THREE.Scene;
var renderer: THREE.WebGLRenderer;
- var mesh: THREE.Mesh;
- var helper: THREE.SkeletonHelper;
- var mixer: THREE.AnimationMixer;
+ var model: THREE.Scene;
+ var face: THREE.Mesh;
- var mouseX = 0, mouseY = 0;
+ type Emote = 'Jump' | 'Yes' | 'No' | 'Wave' | 'Punch' | 'ThumbsUp';
- var windowHalfX = window.innerWidth / 2;
- var windowHalfY = window.innerHeight / 2;
-
- var clock = new THREE.Clock();
-
- document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+ var api: { [name in Emote]?: () => void; } & { state: string; } = {state: 'Walking'};
init();
animate();
function init() {
+ container = document.createElement('div');
+ document.body.appendChild(container);
- container = document.getElementById( 'container' );
-
- camera = new THREE.PerspectiveCamera( 30, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
- camera.position.z = 2200;
+ camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 100);
+ camera.position.set(-5, 3, 10);
+ camera.lookAt(new THREE.Vector3(0, 2, 0));
scene = new THREE.Scene();
+ scene.background = new THREE.Color(0xe0e0e0);
+ scene.fog = new THREE.Fog(0xe0e0e0, 20, 100);
- scene.fog = new THREE.Fog( 0xffffff, 2000, 10000 );
+ clock = new THREE.Clock();
- scene.add( camera );
+ // lights
+ var light: THREE.Light = new THREE.HemisphereLight(0xffffff, 0x444444);
+ light.position.set(0, 20, 0);
+ scene.add(light);
- // GROUND
+ light = new THREE.DirectionalLight(0xffffff);
+ light.position.set(0, 20, 10);
+ scene.add(light);
- var geometry = new THREE.PlaneBufferGeometry( 16000, 16000 );
- var material = new THREE.MeshPhongMaterial( { emissive: 0x888888 } );
+ // ground
+ var mesh = new THREE.Mesh(new THREE.PlaneBufferGeometry(2000, 2000), new THREE.MeshPhongMaterial({
+ color: 0x999999,
+ depthWrite: false
+ }));
+ mesh.rotation.x = -Math.PI / 2;
+ scene.add(mesh);
- var ground = new THREE.Mesh( geometry, material );
- ground.position.set( 0, FLOOR, 0 );
- ground.rotation.x = -Math.PI/2;
- scene.add( ground );
+ var grid = new THREE.GridHelper(200, 40, 0x000000, 0x000000);
+ (grid.material as THREE.LineBasicMaterial).opacity = 0.2;
+ (grid.material as THREE.LineBasicMaterial).transparent = true;
+ scene.add(grid);
- ground.receiveShadow = true;
+ // model
+ var loader = new THREE.GLTFLoader();
+ loader.load('models/gltf/RobotExpressive/RobotExpressive.glb', function (gltf) {
+ model = gltf.scene;
+ scene.add(model);
+ createGUI(model, gltf.animations);
+ }, undefined, function (e) {
+ console.error(e);
+ });
- // LIGHTS
-
- scene.add( new THREE.HemisphereLight( 0x111111, 0x444444 ) );
-
- var light = new THREE.DirectionalLight( 0xebf3ff, 1.5 );
- light.position.set( 0, 140, 500 ).multiplyScalar( 1.1 );
- scene.add( light );
-
- light.castShadow = true;
-
- light.shadowMapWidth = 1024;
- light.shadowMapHeight = 1024;
-
- var d = 390;
-
- light.shadowCameraLeft = -d;
- light.shadowCameraRight = d;
- light.shadowCameraTop = d * 1.5;
- light.shadowCameraBottom = -d;
-
- light.shadowCameraFar = 3500;
- //light.shadowCameraVisible = true;
-
- // RENDERER
-
- renderer = new THREE.WebGLRenderer( { antialias: true } );
- renderer.setClearColor( scene.fog.color );
- renderer.setPixelRatio( window.devicePixelRatio );
- renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
- renderer.domElement.style.position = "relative";
-
- container.appendChild( renderer.domElement );
-
- renderer.gammaInput = true;
+ renderer = new THREE.WebGLRenderer({antialias: true});
+ renderer.setPixelRatio(window.devicePixelRatio);
+ renderer.setSize(window.innerWidth, window.innerHeight);
renderer.gammaOutput = true;
+ renderer.gammaFactor = 2.2;
+ container.appendChild(renderer.domElement);
- renderer.shadowMap.enabled = true;
-
-
- // STATS
+ window.addEventListener('resize', onWindowResize, false);
+ // stats
stats = new Stats();
- container.appendChild( stats.dom );
+ container.appendChild(stats.dom);
+ }
- //
+ function createGUI(model: THREE.Scene, animations: THREE.AnimationClip[]) {
+ var states = ['Idle', 'Walking', 'Running', 'Dance', 'Death', 'Sitting', 'Standing'];
+ var emotes: Emote[] = ['Jump', 'Yes', 'No', 'Wave', 'Punch', 'ThumbsUp'];
- var loader = new THREE.JSONLoader();
- loader.load( "models/skinned/knight.js", function ( geometry, materials ) {
+ gui = new dat.GUI();
- createScene( geometry, materials as THREE.MeshPhongMaterial[], 0, FLOOR, -300, 60 )
+ mixer = new THREE.AnimationMixer(model);
- } );
+ actions = {};
- // GUI
+ for (var i = 0; i < animations.length; i++) {
+ var clip = animations[i];
+ var action = mixer.clipAction(clip);
+ actions[clip.name] = action;
- initGUI();
+ if (emotes.indexOf(clip.name as Emote) >= 0 || states.indexOf(clip.name) >= 4) {
+ action.clampWhenFinished = true;
+ action.loop = THREE.LoopOnce;
+ }
+ }
- //
+ // states
+ var statesFolder = gui.addFolder('States');
- window.addEventListener( 'resize', onWindowResize, false );
+ var clipCtrl = statesFolder.add(api, 'state').options(states);
+ clipCtrl.onChange(function () {
+ fadeToAction(api.state, 0.5);
+ });
+
+ statesFolder.open();
+
+ // emotes
+ var emoteFolder = gui.addFolder('Emote');
+
+ function createEmoteCallback(name: Emote) {
+ api[name] = function () {
+ fadeToAction(name, 0.2);
+ mixer.addEventListener('finished', restoreState);
+ };
+
+ emoteFolder.add(api, name);
+ }
+
+ function restoreState() {
+ mixer.removeEventListener('finished', restoreState);
+
+ fadeToAction(api.state, 0.2);
+ }
+
+ for (var i = 0; i < emotes.length; i++) {
+ createEmoteCallback(emotes[i]);
+ }
+
+ emoteFolder.open();
+
+ // expressions
+ face = model.getObjectByName('Head_2') as THREE.Mesh;
+
+ var expressions = Object.keys(face.morphTargetDictionary);
+ var expressionFolder = gui.addFolder('Expressions');
+
+ for (var i = 0; i < expressions.length; i++) {
+ expressionFolder.add(face.morphTargetInfluences, i.toString(), 0, 1, 0.01).name(expressions[i]);
+ }
+
+ activeAction = actions['Walking'];
+ activeAction.play();
+
+ expressionFolder.open();
+ }
+
+ function fadeToAction(name: string, duration: number) {
+ previousAction = activeAction;
+ activeAction = actions[name];
+
+ if (previousAction !== activeAction) {
+ previousAction.fadeOut(duration);
+ }
+
+ activeAction
+ .reset()
+ .setEffectiveTimeScale(1)
+ .setEffectiveWeight(1)
+ .fadeIn(duration)
+ .play();
}
function onWindowResize() {
-
- windowHalfX = window.innerWidth / 2;
- windowHalfY = window.innerHeight / 2;
-
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
- renderer.setSize( window.innerWidth, window.innerHeight );
-
- }
-
- function createScene( geometry: THREE.Geometry, materials: THREE.MeshPhongMaterial[], x: number, y: number, z: number, s: number ) {
-
- //ensureLoop( geometry.animation );
-
- geometry.computeBoundingBox();
- var bb = geometry.boundingBox;
-
- var path = "textures/cube/Park2/";
- var format = '.jpg';
- var urls = [
- path + 'posx' + format, path + 'negx' + format,
- path + 'posy' + format, path + 'negy' + format,
- path + 'posz' + format, path + 'negz' + format
- ];
-
- for ( var i = 0; i < materials.length; i ++ ) {
-
- var m = materials[ i ];
- m.skinning = true;
- m.morphTargets = true;
-
- m.specular.setHSL( 0, 0, 0.1 );
-
- m.color.setHSL( 0.6, 0, 0.6 );
-
- //m.map = map;
- //m.envMap = envMap;
- //m.bumpMap = bumpMap;
- //m.bumpScale = 2;
-
- //m.combine = THREE.MixOperation;
- //m.reflectivity = 0.75;
-
- }
-
- mesh = new THREE.SkinnedMesh( geometry, new THREE.MeshFaceMaterial( materials ) );
- mesh.position.set( x, y - bb.min.y * s, z );
- mesh.scale.set( s, s, s );
- scene.add( mesh );
-
- mesh.castShadow = true;
- mesh.receiveShadow = true;
-
- helper = new THREE.SkeletonHelper( mesh );
- //helper.material.linewidth = 3;
- helper.visible = false;
- scene.add( helper );
-
-
- var clipMorpher = THREE.AnimationClip.CreateFromMorphTargetSequence( 'facialExpressions', (mesh.geometry as THREE.Geometry).morphTargets, 3, true );
- var clipBones = geometry.animations[0];
-
- mixer = new THREE.AnimationMixer( mesh );
- }
-
- function initGUI() {
- mesh.visible = true;
- helper.visible = true;
- }
-
- function onDocumentMouseMove( event: MouseEvent ) {
-
- mouseX = ( event.clientX - windowHalfX );
- mouseY = ( event.clientY - windowHalfY );
-
+ renderer.setSize(window.innerWidth, window.innerHeight);
}
//
-
function animate() {
-
- requestAnimationFrame( animate );
-
- render();
+ var dt = clock.getDelta();
+ if (mixer) mixer.update(dt);
+ requestAnimationFrame(animate);
+ renderer.render(scene, camera);
stats.update();
-
}
-
- function render() {
-
- var delta = 0.75 * clock.getDelta();
-
- camera.position.x += ( mouseX - camera.position.x ) * .05;
- camera.position.y = THREE.Math.clamp( camera.position.y + ( - mouseY - camera.position.y ) * .05, 0, 1000 );
-
- camera.lookAt( scene.position );
-
- if( mixer ) {
- mixer.update( delta );
- helper.update();
- }
-
- renderer.render( scene, camera );
-
- }
-}
\ No newline at end of file
+}
diff --git a/types/three/three-core.d.ts b/types/three/three-core.d.ts
index 96c40c7496..f39d28b565 100755
--- a/types/three/three-core.d.ts
+++ b/types/three/three-core.d.ts
@@ -224,7 +224,7 @@ type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint
// Animation ////////////////////////////////////////////////////////////////////////////////////////
export class AnimationAction {
- loop: boolean;
+ loop: AnimationActionLoopStyles;
time: number;
timeScale: number;
weight: number;