Merge pull request #12 from printempw/master
Refactor animations and some minor updates
This commit is contained in:
commit
e09af4093d
41
README.md
41
README.md
|
|
@ -28,28 +28,37 @@ Three.js powered Minecraft skin viewer.
|
||||||
capeUrl: "img/cape.png"
|
capeUrl: "img/cape.png"
|
||||||
});
|
});
|
||||||
|
|
||||||
// change the skin and cape
|
// Change the textures
|
||||||
// skinViewer.skinUrl = "img/skin.png";
|
skinViewer.skinUrl = "img/skin2.png";
|
||||||
// skinViewer.capeUrl = "img/cape.png";
|
skinViewer.capeUrl = "img/cape2.png";
|
||||||
|
|
||||||
// change the width and height
|
// Resize the skin viewer
|
||||||
// skinViewer.width = 300;
|
skinViewer.width = 300;
|
||||||
// skinViewer.height = 400;
|
skinViewer.height = 400;
|
||||||
|
|
||||||
// enable the mouse control feature
|
// Control objects with your mouse!
|
||||||
let control = new skinview3d.SkinControl(skinViewer);
|
let control = skinview3d.createOrbitControls(skinViewer);
|
||||||
|
control.enableRotate = true;
|
||||||
// disable the 'right click to play/pause' feature
|
control.enableZoom = false;
|
||||||
// control.enableAnimationControl = false;
|
control.enablePan = false;
|
||||||
|
|
||||||
skinViewer.animation = new skinview3d.CompositeAnimation();
|
skinViewer.animation = new skinview3d.CompositeAnimation();
|
||||||
|
|
||||||
// add an animation
|
// Add an animation
|
||||||
let walk = skinViewer.animation.add(skinview3d.WalkAnimation);
|
let walk = skinViewer.animation.add(skinview3d.WalkingAnimation);
|
||||||
|
// Add another animation
|
||||||
|
let rotate = skinViewer.animation.add(skinview3d.RotatingAnimation);
|
||||||
|
// Remove an animation, stop walking dude
|
||||||
|
walk.remove();
|
||||||
|
// And run for now!
|
||||||
|
let run = skinViewer.animation.add(skinview3d.RunningAnimation);
|
||||||
|
|
||||||
// set its speed and some others
|
// Set the speed of an animation
|
||||||
walk.speed = 1.5;
|
run.speed = 3;
|
||||||
// walk.paused = true;
|
// Pause single animation
|
||||||
|
run.paused = true;
|
||||||
|
// Pause all animations!
|
||||||
|
skinViewer.animationPaused = true;
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,17 +55,73 @@ class CompositeAnimation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let WalkAnimation = (player, time) => {
|
let WalkingAnimation = (player, time) => {
|
||||||
let skin = player.skin;
|
let skin = player.skin;
|
||||||
let angleRot = time + Math.PI / 2;
|
|
||||||
|
|
||||||
// Leg Swing
|
// Multiply by animation's natural speed
|
||||||
skin.leftLeg.rotation.x = Math.cos(angleRot);
|
time *= 8;
|
||||||
skin.rightLeg.rotation.x = Math.cos(angleRot + (Math.PI));
|
|
||||||
|
|
||||||
// Arm Swing
|
// Leg swing
|
||||||
skin.leftArm.rotation.x = Math.cos(angleRot + (Math.PI));
|
skin.leftLeg.rotation.x = Math.sin(time) * 0.5;
|
||||||
skin.rightArm.rotation.x = Math.cos(angleRot);
|
skin.rightLeg.rotation.x = Math.sin(time + Math.PI) * 0.5;
|
||||||
|
|
||||||
|
// Arm swing
|
||||||
|
skin.leftArm.rotation.x = Math.sin(time + Math.PI) * 0.5;
|
||||||
|
skin.rightArm.rotation.x = Math.sin(time) * 0.5;
|
||||||
|
let basicArmRotationZ = Math.PI * 0.02;
|
||||||
|
skin.leftArm.rotation.z = Math.cos(time) * 0.03 + basicArmRotationZ;
|
||||||
|
skin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.03 - basicArmRotationZ;
|
||||||
|
|
||||||
|
// Head shaking with different frequency & amplitude
|
||||||
|
skin.head.rotation.y = Math.sin(time / 4) * 0.2;
|
||||||
|
skin.head.rotation.x = Math.sin(time / 5) * 0.1;
|
||||||
|
|
||||||
|
// Always add an angle for cape around the x axis
|
||||||
|
let basicCapeRotationX = Math.PI * 0.06;
|
||||||
|
player.cape.rotation.x = Math.sin(time / 1.5) * 0.06 + basicCapeRotationX;
|
||||||
};
|
};
|
||||||
|
|
||||||
export { CompositeAnimation, WalkAnimation, invokeAnimation };
|
let RunningAnimation = (player, time) => {
|
||||||
|
let skin = player.skin;
|
||||||
|
|
||||||
|
time *= 15;
|
||||||
|
|
||||||
|
// Leg swing with larger amplitude
|
||||||
|
skin.leftLeg.rotation.x = Math.cos(time + Math.PI) * 1.3;
|
||||||
|
skin.rightLeg.rotation.x = Math.cos(time) * 1.3;
|
||||||
|
|
||||||
|
// Arm swing
|
||||||
|
skin.leftArm.rotation.x = Math.cos(time) * 1.5;
|
||||||
|
skin.rightArm.rotation.x = Math.cos(time + Math.PI) * 1.5;
|
||||||
|
let basicArmRotationZ = Math.PI * 0.1;
|
||||||
|
skin.leftArm.rotation.z = Math.cos(time) * 0.1 + basicArmRotationZ;
|
||||||
|
skin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.1 - basicArmRotationZ;
|
||||||
|
|
||||||
|
// Jumping
|
||||||
|
player.position.y = Math.cos(time * 2);
|
||||||
|
// Dodging when running
|
||||||
|
player.position.x = Math.cos(time) * 0.15;
|
||||||
|
// Slightly tilting when running
|
||||||
|
player.rotation.z = Math.cos(time + Math.PI) * 0.01;
|
||||||
|
|
||||||
|
// Apply higher swing frequency, lower amplitude,
|
||||||
|
// and greater basic rotation around x axis,
|
||||||
|
// to cape when running.
|
||||||
|
let basicCapeRotationX = Math.PI * 0.3;
|
||||||
|
player.cape.rotation.x = Math.sin(time * 2) * 0.1 + basicCapeRotationX;
|
||||||
|
|
||||||
|
// What about head shaking?
|
||||||
|
// You shouldn't glance right and left when running dude :P
|
||||||
|
};
|
||||||
|
|
||||||
|
let RotatingAnimation = (player, time) => {
|
||||||
|
player.rotation.y = time;
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
CompositeAnimation,
|
||||||
|
invokeAnimation,
|
||||||
|
WalkingAnimation,
|
||||||
|
RunningAnimation,
|
||||||
|
RotatingAnimation
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -593,4 +593,17 @@ class OrbitControls extends THREE.EventDispatcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { OrbitControls };
|
function createOrbitControls(skinViewer) {
|
||||||
|
let control = new OrbitControls(skinViewer.camera, skinViewer.renderer.domElement);
|
||||||
|
|
||||||
|
// default configuration
|
||||||
|
control.enablePan = false;
|
||||||
|
control.target = new THREE.Vector3(0, -12, 0);
|
||||||
|
control.minDistance = 10;
|
||||||
|
control.maxDistance = 256;
|
||||||
|
control.update();
|
||||||
|
|
||||||
|
return control;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { OrbitControls, createOrbitControls };
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,10 @@
|
||||||
export { SkinObject, CapeObject, PlayerObject } from "./model";
|
export { SkinObject, CapeObject, PlayerObject } from "./model";
|
||||||
export { SkinViewer, SkinControl } from "./viewer";
|
export { SkinViewer } from "./viewer";
|
||||||
export { invokeAnimation, CompositeAnimation, WalkAnimation } from "./animation";
|
export { OrbitControls, createOrbitControls } from "./orbit_controls";
|
||||||
|
export {
|
||||||
|
invokeAnimation,
|
||||||
|
CompositeAnimation,
|
||||||
|
WalkingAnimation,
|
||||||
|
RunningAnimation,
|
||||||
|
RotatingAnimation
|
||||||
|
} from "./animation";
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { PlayerObject } from "./model";
|
import { PlayerObject } from "./model";
|
||||||
import { OrbitControls } from "./orbit_controls";
|
|
||||||
import { invokeAnimation } from "./animation";
|
import { invokeAnimation } from "./animation";
|
||||||
|
|
||||||
function copyImage(context, sX, sY, w, h, dX, dY, flipHorizontal) {
|
function copyImage(context, sX, sY, w, h, dX, dY, flipHorizontal) {
|
||||||
|
|
@ -81,9 +80,10 @@ class SkinViewer {
|
||||||
// scene
|
// scene
|
||||||
this.scene = new THREE.Scene();
|
this.scene = new THREE.Scene();
|
||||||
|
|
||||||
this.camera = new THREE.PerspectiveCamera(75);
|
// Use smaller fov to avoid distortion
|
||||||
|
this.camera = new THREE.PerspectiveCamera(40);
|
||||||
this.camera.position.y = -12;
|
this.camera.position.y = -12;
|
||||||
this.camera.position.z = 30;
|
this.camera.position.z = 60;
|
||||||
|
|
||||||
this.renderer = new THREE.WebGLRenderer({ angleRot: true, alpha: true, antialias: false });
|
this.renderer = new THREE.WebGLRenderer({ angleRot: true, alpha: true, antialias: false });
|
||||||
this.renderer.setSize(300, 300); // default size
|
this.renderer.setSize(300, 300); // default size
|
||||||
|
|
@ -227,31 +227,4 @@ class SkinViewer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SkinControl {
|
export { SkinViewer };
|
||||||
constructor(skinViewer) {
|
|
||||||
this.enableAnimationControl = true;
|
|
||||||
this.skinViewer = skinViewer;
|
|
||||||
|
|
||||||
this.orbitControls = new OrbitControls(skinViewer.camera, skinViewer.renderer.domElement);
|
|
||||||
this.orbitControls.enablePan = false;
|
|
||||||
this.orbitControls.target = new THREE.Vector3(0, -12, 0);
|
|
||||||
this.orbitControls.minDistance = 10;
|
|
||||||
this.orbitControls.maxDistance = 256;
|
|
||||||
this.orbitControls.update();
|
|
||||||
|
|
||||||
this.animationPauseListener = e => {
|
|
||||||
if (this.enableAnimationControl) {
|
|
||||||
e.preventDefault();
|
|
||||||
this.skinViewer.animationPaused = !this.skinViewer.animationPaused;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.skinViewer.domElement.addEventListener("contextmenu", this.animationPauseListener, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
dispose() {
|
|
||||||
this.skinViewer.domElement.removeEventListener("contextmenu", this.animationPauseListener, false);
|
|
||||||
this.orbitControls.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { SkinViewer, SkinControl };
|
|
||||||
|
|
|
||||||
|
|
@ -28,4 +28,6 @@ export class CompositeAnimation implements IAnimation {
|
||||||
public play(player: PlayerObject, time: number): void;
|
public play(player: PlayerObject, time: number): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WalkAnimation: AnimationFn;
|
export const WalkingAnimation: AnimationFn;
|
||||||
|
export const RunningAnimation: AnimationFn;
|
||||||
|
export const RotatingAnimation: AnimationFn;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
import * as THREE from "three";
|
||||||
|
import { SkinViewer } from "./viewer";
|
||||||
|
|
||||||
|
export class OrbitControls {
|
||||||
|
|
||||||
|
public readonly object: THREE.Camera;
|
||||||
|
public readonly domElement: HTMLElement | HTMLDocument;
|
||||||
|
|
||||||
|
public enabled: boolean;
|
||||||
|
public target: THREE.Vector3;
|
||||||
|
|
||||||
|
public minDistance: number;
|
||||||
|
public maxDistance: number;
|
||||||
|
|
||||||
|
public minZoom: number;
|
||||||
|
public maxZoom: number;
|
||||||
|
|
||||||
|
public minPolarAngle: number;
|
||||||
|
public maxPolarAngle: number;
|
||||||
|
|
||||||
|
public minAzimuthAngle: number;
|
||||||
|
public maxAzimuthAngle: number;
|
||||||
|
|
||||||
|
public enableDamping: boolean;
|
||||||
|
public dampingFactor: number;
|
||||||
|
|
||||||
|
public enableZoom: boolean;
|
||||||
|
public zoomSpeed: number;
|
||||||
|
|
||||||
|
public enableRotate: boolean;
|
||||||
|
public rotateSpeed: number;
|
||||||
|
|
||||||
|
public enablePan: boolean;
|
||||||
|
public keyPanSpeed: number;
|
||||||
|
|
||||||
|
public autoRotate: boolean;
|
||||||
|
public autoRotateSpeed: number;
|
||||||
|
|
||||||
|
public enableKeys: boolean;
|
||||||
|
public keys: { LEFT: number, UP: number, RIGHT: number, BOTTOM: number };
|
||||||
|
|
||||||
|
public mouseButtons: { ORBIT: THREE.MOUSE, ZOOM: THREE.MOUSE, PAN: THREE.MOUSE };
|
||||||
|
|
||||||
|
constructor(object: THREE.Camera, domElement?: HTMLElement);
|
||||||
|
|
||||||
|
public getPolarAngle(): number;
|
||||||
|
public getAzimuthalAngle(): number;
|
||||||
|
|
||||||
|
public saveState(): void;
|
||||||
|
public reset(): void;
|
||||||
|
|
||||||
|
public update(): boolean;
|
||||||
|
|
||||||
|
public dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createOrbitControls(skinViewer: SkinViewer): OrbitControls;
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
export * from "./model";
|
export * from "./model";
|
||||||
export * from "./animation";
|
export * from "./animation";
|
||||||
export * from "./viewer";
|
export * from "./viewer";
|
||||||
|
export * from "./orbit_controls";
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,10 @@ export class SkinViewer {
|
||||||
public dispose(): void;
|
public dispose(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SkinControl {
|
export class MouseControl {
|
||||||
public enableAnimationControl: boolean;
|
public pan: boolean;
|
||||||
|
public zoom: boolean;
|
||||||
|
public rotation: boolean;
|
||||||
public readonly skinViewer: SkinViewer;
|
public readonly skinViewer: SkinViewer;
|
||||||
|
|
||||||
constructor(skinViewer: SkinViewer);
|
constructor(skinViewer: SkinViewer);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue