Skip to content

Commit

Permalink
Merge branch 'master' into AnimSwordWalkPr
Browse files Browse the repository at this point in the history
  • Loading branch information
gonnavis committed Apr 18, 2022
2 parents dd0ea6f + d3d4f55 commit 276f6b5
Show file tree
Hide file tree
Showing 101 changed files with 6,359 additions and 688 deletions.
5 changes: 3 additions & 2 deletions animations-baker.js
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,8 @@ const {CharsetEncoder} = require('three/examples/js/libs/mmdparser.js');
const rootBone = object; // not really a bone
const leftFootBone = bones.find(b => b.name === 'mixamorigLeftFoot');
const rightFootBone = bones.find(b => b.name === 'mixamorigRightFoot');
const allOnes = arr => arr.every(v => v === 1);
const epsilon = 0.001;
const allOnesEpsilon = arr => arr.every(v => Math.abs(1 - v) < epsilon);

const bonePositionInterpolants = {};
const boneQuaternionInterpolants = {};
Expand All @@ -362,7 +363,7 @@ const {CharsetEncoder} = require('three/examples/js/libs/mmdparser.js');
const boneInterpolant = new THREE.QuaternionLinearInterpolant(track.times, track.values, track.getValueSize());
boneQuaternionInterpolants[boneName] = boneInterpolant;
} else if (/\.scale$/.test(track.name)) {
if (allOnes(track.values)) {
if (allOnesEpsilon(track.values)) {
const index = tracks.indexOf(track);
tracksToRemove.push(index);
} else {
Expand Down
125 changes: 125 additions & 0 deletions avatar-screenshotter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import * as THREE from 'three';
import metaversefile from './metaversefile-api.js';
import Avatar from './avatars/avatars.js';
import npcManager from './npc-manager.js';
import dioramaManager from './diorama.js';

const FPS = 60;

const _makeLights = () => {
const directionalLight = new THREE.DirectionalLight(0xFFFFFF, 5);
directionalLight.position.set(1, 1.5, -2);
directionalLight.updateMatrixWorld();

return [
directionalLight,
];
};

export const screenshotAvatarUrl = async ({
start_url,
width = 300,
height = 300,
}) => {
const app = await metaversefile.createAppAsync({
start_url,
});
return await screenshotAvatarApp({
app,
width,
height,
});
};
export const screenshotAvatarApp = async ({
app,
width = 300,
height = 300,
}) => {
await Avatar.waitForLoad();

const position = new THREE.Vector3(0, 1.5, 0);
const quaternion = new THREE.Quaternion();
const scale = new THREE.Vector3(1, 1, 1);
const player = npcManager.createNpc({
name: 'npc',
avatarApp: app,
position,
quaternion,
scale,
detached: true,
});

let now = 0;
const timeDiff = 1000/FPS;

const _setTransform = () => {
player.position.y = player.avatar.height;
player.updateMatrixWorld();
};
_setTransform();

const _initializeAnimation = () => {
player.avatar.setTopEnabled(false);
player.avatar.setHandEnabled(0, false);
player.avatar.setHandEnabled(1, false);
player.avatar.setBottomEnabled(false);
player.avatar.inputs.hmd.position.y = player.avatar.height;
player.avatar.inputs.hmd.quaternion.setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI);
player.avatar.inputs.hmd.updateMatrixWorld();
player.addAction({
type: 'facepose',
emotion: 'angry',
});
};
const _preAnimate = () => {
for (let i = 0; i < FPS*2; i++) {
_animate(now, timeDiff);
};
};
const _updateTarget = (timestamp, timeDiff) => {
target.matrixWorld.copy(player.avatar.modelBones.Head.matrixWorld)
.decompose(target.position, target.quaternion, target.scale);
target.position.set(player.position.x, target.position.y, player.position.z);
target.quaternion.copy(player.quaternion);
target.matrixWorld.compose(target.position, target.quaternion, target.scale);
};
const _animate = (timestamp, timeDiff) => {
player.updateAvatar(timestamp, timeDiff);
};

// rendering
const writeCanvas = document.createElement('canvas');
writeCanvas.width = width;
writeCanvas.height = height;

const localLights = _makeLights();
const objects = localLights.concat([
player.avatar.model,
]);
const target = new THREE.Object3D();
const diorama = dioramaManager.createPlayerDiorama({
// target: player,
target,
objects,
lights: false,
// label: true,
// outline: true,
// grassBackground: true,
// glyphBackground: true,
detached: true,
});
diorama.addCanvas(writeCanvas);
diorama.setClearColor(0xFFFFFF, 1);

const _render = () => {
_initializeAnimation();
_preAnimate();
_updateTarget(now, timeDiff);
diorama.update(now, timeDiff);
};
_render();

diorama.destroy();

return writeCanvas;
};
76 changes: 67 additions & 9 deletions avatars/animationHelpers.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {Vector3, Quaternion, AnimationClip} from 'three';
import metaversefile from 'metaversefile';
import {VRMSpringBoneImporter, VRMLookAtApplyer, VRMCurveMapper} from '@pixiv/three-vrm/lib/three-vrm.module.js';
import easing from '../easing.js';
import {/*VRMSpringBoneImporter, VRMLookAtApplyer, */ VRMCurveMapper} from '@pixiv/three-vrm/lib/three-vrm.module.js';
// import easing from '../easing.js';
import {easing} from '../math-utils.js';
import loaders from '../loaders.js';
import {zbdecode} from 'zjs/encoding.mjs';

Expand All @@ -26,9 +27,9 @@ import {
} from '../util.js';

import {
idleFactorSpeed,
walkFactorSpeed,
runFactorSpeed,
// idleFactorSpeed,
// walkFactorSpeed,
// runFactorSpeed,
narutoRunTimeFactor,
} from './constants.js';

Expand Down Expand Up @@ -61,6 +62,7 @@ let useAnimations;
let aimAnimations;
let sitAnimations;
let danceAnimations;
let emoteAnimations;
let throwAnimations;
// let crouchAnimations;
let activateAnimations;
Expand All @@ -77,6 +79,7 @@ let lastF;
const defaultSitAnimation = 'chair';
const defaultUseAnimation = 'combo';
const defaultDanceAnimation = 'dansu';
const defaultEmoteAnimation = 'angry';
const defaultThrowAnimation = 'throw';
// const defaultCrouchAnimation = 'crouch';
const defaultActivateAnimation = 'activate';
Expand Down Expand Up @@ -355,6 +358,24 @@ export const loadPromise = (async () => {
dansu: animations.find(a => a.isDancing),
powerup: animations.find(a => a.isPowerUp),
};
emoteAnimations = {
alert: animations.find(a => a.isAlert),
alertSoft: animations.find(a => a.isAlertSoft),
angry: animations.find(a => a.isAngry),
angrySoft: animations.find(a => a.isAngrySoft),
embarrassed: animations.find(a => a.isEmbarrassed),
embarrassedSoft: animations.find(a => a.isEmbarrassedSoft),
headNod: animations.find(a => a.isHeadNod),
headNodSoft: animations.find(a => a.isHeadNodSingle),
headShake: animations.find(a => a.isHeadShake),
headShakeSoft: animations.find(a => a.isHeadShakeSingle),
sad: animations.find(a => a.isSad),
sadSoft: animations.find(a => a.isSadSoft),
surprise: animations.find(a => a.isSurprise),
surpriseSoft: animations.find(a => a.isSurpriseSoft),
victory: animations.find(a => a.isVictory),
victorySoft: animations.find(a => a.isVictorySoft),
};
throwAnimations = {
throw: animations.find(a => a.isThrow),
};
Expand Down Expand Up @@ -774,6 +795,11 @@ export const _applyAnimation = (avatar, now, moveFactors) => {
}
activeAvatar.lastBackwardFactor = mirrorFactor;

if (activeAvatar.emoteAnimation !== activeAvatar.lastEmoteAnimation) {
activeAvatar.lastEmoteTime = activeAvatar.emoteAnimation ? now : 0;
}
activeAvatar.lastEmoteAnimation = activeAvatar.emoteAnimation;

const _handleDefault = spec => {
const {
animationTrackName: k,
Expand Down Expand Up @@ -836,7 +862,7 @@ export const _applyAnimation = (avatar, now, moveFactors) => {
};
}

if (activeAvatar.danceTime > 0) {
if (activeAvatar.danceFactor > 0) {
return spec => {
const {
animationTrackName: k,
Expand All @@ -853,8 +879,39 @@ export const _applyAnimation = (avatar, now, moveFactors) => {
const t2 = (now / 1000) % danceAnimation.duration;
const v2 = src2.evaluate(t2);

const danceTimeS = activeAvatar.danceTime / crouchMaxTime;
const f = Math.min(Math.max(danceTimeS, 0), 1);
const danceFactorS = activeAvatar.danceFactor / crouchMaxTime;
const f = Math.min(Math.max(danceFactorS, 0), 1);
lerpFn
.call(
dst,
localQuaternion.fromArray(v2),
f,
);

_clearXZ(dst, isPosition);
};
}

if (activeAvatar.emoteFactor > 0) {
return spec => {
const {
animationTrackName: k,
dst,
lerpFn,
// isTop,
isPosition,
} = spec;

_handleDefault(spec);

const emoteAnimation = emoteAnimations[activeAvatar.emoteAnimation || defaultEmoteAnimation];
const src2 = emoteAnimation.interpolants[k];
const emoteTime = now - avatar.lastEmoteTime;
const t2 = Math.min(emoteTime / 1000, emoteAnimation.duration);
const v2 = src2.evaluate(t2);

const emoteFactorS = activeAvatar.emoteFactor / crouchMaxTime;
const f = Math.min(Math.max(emoteFactorS, 0), 1);
lerpFn
.call(
dst,
Expand Down Expand Up @@ -1153,7 +1210,8 @@ export const _applyAnimation = (avatar, now, moveFactors) => {
export {
animations,
animationStepIndices,
cubicBezier
emoteAnimations,
// cubicBezier,
};

export const getClosest2AnimationAngles = (key, angle) => {
Expand Down
Loading

0 comments on commit 276f6b5

Please sign in to comment.