Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: animation assigner and VRM extension detection #1258

Merged
merged 4 commits into from
Jun 7, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions samples/test_e2e/VRM1Animation/main.ts
Original file line number Diff line number Diff line change
@@ -72,8 +72,7 @@ declare const Stats: any;
animGltf2Result.unwrapForce(),
vrmModelResult.unwrapForce(),
false,
'global',
animGltfModel
'global'
);

// for (let i = 0; i < 1; i++) {
6 changes: 4 additions & 2 deletions samples/test_e2e/VRMAnimation/main.ts
Original file line number Diff line number Diff line change
@@ -72,7 +72,8 @@ declare const Stats: any;
vrmRootEntity,
animGltf2Result.unwrapForce(),
vrmModelResult.unwrapForce(),
false
false,
'none'
);

for (let i = 0; i < 1; i++) {
@@ -91,7 +92,8 @@ declare const Stats: any;
vrmRootEntity2nd,
animGltf2Result.unwrapForce(),
vrmModelResult.unwrapForce(),
false
false,
'none'
);
}
}
11 changes: 11 additions & 0 deletions src/foundation/components/Animation/AnimationComponent.ts
Original file line number Diff line number Diff line change
@@ -1005,5 +1005,16 @@ export class AnimationComponent extends Component {
this.__isAnimating = component.__isAnimating;
this._animationRetarget = component._animationRetarget;
}

setAnimationRetarget(retarget: IAnimationRetarget) {
this._animationRetarget = retarget;

this.__transformComponent = EntityRepository.getComponentOfEntity(
this.__entityUid,
TransformComponent
) as TransformComponent;

this.__transformComponent?._backupTransformAsRest();
}
}
ComponentRepository.registerComponentClass(AnimationComponent);
83 changes: 46 additions & 37 deletions src/foundation/importer/AnimationAssigner.ts
Original file line number Diff line number Diff line change
@@ -20,21 +20,30 @@ type RetargetMode = 'none' | 'global' | 'global2' | 'absolute';
export class AnimationAssigner {
private static __instance: AnimationAssigner;

/**
* Assign Animation Function
*
* @param rootEntity - The root entity of the model which you want to assign animation.
* @param gltfModel - The glTF model that has animation data.
* @param vrmModel - The corresponding VRM model to the glTF model.
* @param isSameSkeleton
* @param retargetMode - Retarget mode. 'none' | 'global' | 'global2' | 'absolute'
* @param srcRootEntityForRetarget
* @returns
*/
assignAnimation(
rootEntity: ISceneGraphEntity,
gltfModel: RnM2,
vrmModel: Vrm0x | Vrm1,
isSameSkeleton: boolean,
retargetMode: RetargetMode = 'none',
srcRootEntityForRetarget?: ISceneGraphEntity
retargetMode: RetargetMode
) {
this.__setupAnimationForSameSkeleton(
rootEntity,
gltfModel,
vrmModel,
isSameSkeleton,
retargetMode,
srcRootEntityForRetarget
);

return rootEntity;
@@ -165,7 +174,6 @@ export class AnimationAssigner {
vrmModel: Vrm0x | Vrm1,
isSameSkeleton: boolean,
retargetMode: RetargetMode,
srcRootEntityForRetarget?: ISceneGraphEntity
) {
if (gltfModel.animations) {
for (const animation of gltfModel.animations) {
@@ -201,39 +209,40 @@ export class AnimationAssigner {
const newRnEntity = EntityRepository.addComponentToEntity(AnimationComponent, rnEntity);
const animationComponent = newRnEntity.getAnimation();

// apply animation data to the target joint entity
let animationAttributeType = 'translate';
if (channel.target!.path === 'translation') {
animationAttributeType = 'translate';
} else if (channel.target!.path! === 'rotation') {
animationAttributeType = 'quaternion';
} else {
animationAttributeType = channel.target!.path;
}
if (animationAttributeType === 'quaternion') {
animationComponent.setAnimation(
Is.exist(animation.name) ? animation.name! : 'Untitled',
animationAttributeType,
animInputArray!,
animOutputArray!,
4, // Quaternion
AnimationInterpolation.fromString(interpolation)
);
} else if (
animationAttributeType === 'translate' &&
this.__isHips(rootEntity, vrmModel, channel.target!.node!)
) {
animationComponent.setAnimation(
Is.exist(animation.name) ? animation.name! : 'Untitled',
animationAttributeType,
animInputArray!,
animOutputArray!,
3, // translate
AnimationInterpolation.fromString(interpolation)
);
}

if (retargetMode !== 'none' && Is.exist(srcRootEntityForRetarget)) {
if (retargetMode === 'none') {
// apply animation data to the target joint entity
let animationAttributeType = 'translate';
if (channel.target!.path === 'translation') {
animationAttributeType = 'translate';
} else if (channel.target!.path! === 'rotation') {
animationAttributeType = 'quaternion';
} else {
animationAttributeType = channel.target!.path;
}
if (animationAttributeType === 'quaternion') {
animationComponent.setAnimation(
Is.exist(animation.name) ? animation.name! : 'Untitled',
animationAttributeType,
animInputArray!,
animOutputArray!,
4, // Quaternion
AnimationInterpolation.fromString(interpolation)
);
} else if (
animationAttributeType === 'translate' &&
this.__isHips(rootEntity, vrmModel, channel.target!.node!)
) {
animationComponent.setAnimation(
Is.exist(animation.name) ? animation.name! : 'Untitled',
animationAttributeType,
animInputArray!,
animOutputArray!,
3, // translate
AnimationInterpolation.fromString(interpolation)
);
}
} else {
const gltfEntity = gltfModel.extras.rnEntities[channel.target!.node!];
let retarget: IAnimationRetarget | undefined;
if (retargetMode === 'global') {
@@ -245,7 +254,7 @@ export class AnimationAssigner {
} else {
throw new Error('unknown retarget mode');
}
animationComponent._animationRetarget = retarget;
animationComponent.setAnimationRetarget(retarget);
}
}
}
4 changes: 2 additions & 2 deletions src/foundation/importer/GltfImporter.ts
Original file line number Diff line number Diff line change
@@ -265,12 +265,12 @@ export class GltfImporter {

if (result.isOk()) {
const gltfModel = result.get();
if (gltfModel.extensionsUsed.indexOf('VRMC_vrm') > 0) {
if (gltfModel.extensionsUsed.indexOf('VRMC_vrm') >= 0) {
options.__isImportVRM0x = false;
gltfModel.asset.extras!.rnLoaderOptions!.__isImportVRM0x = false;
options.__importedType = 'vrm1';
await VrmImporter.__importVRM(gltfModel, renderPasses);
} else if (gltfModel.extensionsUsed.indexOf('VRM') > 0) {
} else if (gltfModel.extensionsUsed.indexOf('VRM') >= 0) {
options.__importedType = 'vrm0x';
await Vrm0xImporter.__importVRM0x(gltfModel, renderPasses);
}