mirror of
https://github.com/galacean/engine.git
synced 2026-05-30 23:35:16 +08:00
Fix the bug of animation playback for multiple same type components under an Entity (#2095)
* fix: multi subMesh animation bug
This commit is contained in:
108
e2e/case/animator-multiSubMeshBlendShape.ts
Normal file
108
e2e/case/animator-multiSubMeshBlendShape.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* @title Animation MultiSubMeshBlendShape
|
||||
* @category Animation
|
||||
*/
|
||||
import {
|
||||
Animator,
|
||||
Camera,
|
||||
DirectLight,
|
||||
Logger,
|
||||
SkinnedMeshRenderer,
|
||||
SystemInfo,
|
||||
Vector3,
|
||||
WebGLEngine,
|
||||
GLTFResource,
|
||||
Keyframe,
|
||||
AnimatorController,
|
||||
AnimatorControllerLayer,
|
||||
AnimatorStateMachine,
|
||||
AnimationClip,
|
||||
AnimationFloatArrayCurve
|
||||
} from "@galacean/engine";
|
||||
import { initScreenshot, updateForE2E } from "./.mockForE2E";
|
||||
|
||||
Logger.enable();
|
||||
WebGLEngine.create({ canvas: "canvas" }).then((engine) => {
|
||||
engine.canvas.width = window.innerWidth * SystemInfo.devicePixelRatio;
|
||||
engine.canvas.height = window.innerHeight * SystemInfo.devicePixelRatio;
|
||||
const scene = engine.sceneManager.activeScene;
|
||||
const rootEntity = scene.createRootEntity();
|
||||
|
||||
// camera
|
||||
const cameraEntity = rootEntity.createChild("camera_node");
|
||||
cameraEntity.transform.position = new Vector3(0, 1.5, 1);
|
||||
const camera = cameraEntity.addComponent(Camera);
|
||||
|
||||
const lightNode = rootEntity.createChild("light_node");
|
||||
lightNode.addComponent(DirectLight).intensity = 1.0;
|
||||
lightNode.transform.lookAt(new Vector3(0, 0, 1));
|
||||
lightNode.transform.rotate(new Vector3(-45, -135, 0));
|
||||
|
||||
engine.resourceManager
|
||||
.load<GLTFResource>(
|
||||
"https://mdn.alipayobjects.com/oasis_be/afts/file/A*M_orSIoXP-QAAAAAAAAAAAAADkp5AQ/258To52bs_01.glb"
|
||||
)
|
||||
.then((asset) => {
|
||||
const { defaultSceneRoot } = asset;
|
||||
rootEntity.addChild(defaultSceneRoot);
|
||||
const entity = defaultSceneRoot;
|
||||
defaultSceneRoot.transform.rotation = new Vector3(-90, -0, 0);
|
||||
const animator = entity.addComponent(Animator);
|
||||
|
||||
animator.animatorController = new AnimatorController();
|
||||
const layer = new AnimatorControllerLayer("base");
|
||||
animator.animatorController.addLayer(layer);
|
||||
const stateMachine = (layer.stateMachine = new AnimatorStateMachine());
|
||||
const state = stateMachine.addState("blendShape");
|
||||
const clip = (state.clip = new AnimationClip("blendShape"));
|
||||
|
||||
//custom blendShape curve
|
||||
const blendShapeCurve = new AnimationFloatArrayCurve();
|
||||
let key1 = new Keyframe<Float32Array>();
|
||||
key1.time = 0;
|
||||
let array1 = new Float32Array(52);
|
||||
for (let i = 0; i < array1.length; i++) {
|
||||
array1[i] = 0;
|
||||
if (i == 8) {
|
||||
array1[i] = 0;
|
||||
}
|
||||
}
|
||||
key1.value = array1;
|
||||
|
||||
let key2 = new Keyframe<Float32Array>();
|
||||
key2.time = 0.5;
|
||||
let array2 = new Float32Array(52);
|
||||
for (let i = 0; i < array2.length; i++) {
|
||||
array2[i] = 0;
|
||||
if (i == 8) {
|
||||
array2[i] = 1;
|
||||
}
|
||||
}
|
||||
key2.value = array2;
|
||||
|
||||
let key3 = new Keyframe<Float32Array>();
|
||||
key3.time = 1;
|
||||
let array3 = new Float32Array(52);
|
||||
for (let i = 0; i < array3.length; i++) {
|
||||
array3[i] = 0;
|
||||
if (i == 8) {
|
||||
array3[i] = 0;
|
||||
}
|
||||
}
|
||||
key3.value = array3;
|
||||
|
||||
blendShapeCurve.addKey(key1);
|
||||
blendShapeCurve.addKey(key2);
|
||||
blendShapeCurve.addKey(key3);
|
||||
const skinMeshRenders = entity.getComponentsIncludeChildren<SkinnedMeshRenderer>(SkinnedMeshRenderer, []);
|
||||
|
||||
for (let i = 0, n = skinMeshRenders.length; i < n; i++) {
|
||||
clip.addCurveBinding("", SkinnedMeshRenderer, i, "blendShapeWeights", blendShapeCurve);
|
||||
}
|
||||
animator.play("blendShape");
|
||||
|
||||
updateForE2E(engine, 500);
|
||||
|
||||
initScreenshot(engine, camera);
|
||||
});
|
||||
});
|
||||
@@ -30,6 +30,11 @@ export const E2E_CONFIG = {
|
||||
caseFileName: "animator-customBlendShape",
|
||||
threshold: 0.1
|
||||
},
|
||||
multiSubMeshBlendShape: {
|
||||
category: "Animator",
|
||||
caseFileName: "animator-multiSubMeshBlendShape",
|
||||
threshold: 0.1
|
||||
},
|
||||
event: {
|
||||
category: "Animator",
|
||||
caseFileName: "animator-event",
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a2e3237691c33d1fb0ca40b8d3076a87f29d4f1887ae6852cb3c256fe7605d91
|
||||
size 80713
|
||||
@@ -300,7 +300,6 @@ export class Animator extends Component {
|
||||
const { relativePath } = curve;
|
||||
const targetEntity = curve.relativePath === "" ? entity : entity.findByPath(curve.relativePath);
|
||||
if (targetEntity) {
|
||||
const propertyPath = `${curve.typeIndex}.` + curve.property;
|
||||
const component =
|
||||
curve.typeIndex > 0
|
||||
? targetEntity.getComponents(curve.type, AnimationCurveOwner._components)[curve.typeIndex]
|
||||
@@ -311,7 +310,7 @@ export class Animator extends Component {
|
||||
}
|
||||
|
||||
const { property } = curve;
|
||||
const { instanceId } = targetEntity;
|
||||
const { instanceId } = component;
|
||||
// Get owner
|
||||
const propertyOwners = (curveOwnerPool[instanceId] ||= <Record<string, AnimationCurveOwner<KeyframeValueType>>>(
|
||||
Object.create(null)
|
||||
@@ -322,7 +321,7 @@ export class Animator extends Component {
|
||||
const layerPropertyOwners = (layerCurveOwnerPool[instanceId] ||= <Record<string, AnimationCurveLayerOwner>>(
|
||||
Object.create(null)
|
||||
));
|
||||
const layerOwner = (layerPropertyOwners[propertyPath] ||= curve._createCurveLayerOwner(owner));
|
||||
const layerOwner = (layerPropertyOwners[property] ||= curve._createCurveLayerOwner(owner));
|
||||
|
||||
if (mask && mask.pathMasks.length) {
|
||||
layerOwner.isActive = mask.getPathMask(relativePath)?.active ?? true;
|
||||
|
||||
@@ -265,10 +265,10 @@ describe("Animator test", function () {
|
||||
);
|
||||
|
||||
let layerData = animator["_animatorLayersData"][1];
|
||||
const layerCurveOwner = layerData.curveOwnerPool[targetEntity.instanceId]["0.rotationQuaternion"];
|
||||
const parentLayerCurveOwner = layerData.curveOwnerPool[parentEntity.instanceId]["0.rotationQuaternion"];
|
||||
const layerCurveOwner = layerData.curveOwnerPool[targetEntity.transform.instanceId]["rotationQuaternion"];
|
||||
const parentLayerCurveOwner = layerData.curveOwnerPool[parentEntity.transform.instanceId]["rotationQuaternion"];
|
||||
|
||||
let childLayerCurveOwner = layerData.curveOwnerPool[childEntity.instanceId]["0.rotationQuaternion"];
|
||||
let childLayerCurveOwner = layerData.curveOwnerPool[childEntity.transform.instanceId]["rotationQuaternion"];
|
||||
|
||||
expect(layerCurveOwner.isActive).to.eq(false);
|
||||
expect(parentLayerCurveOwner.isActive).to.eq(true);
|
||||
@@ -279,7 +279,7 @@ describe("Animator test", function () {
|
||||
animator.animatorController.addLayer(additiveLayer);
|
||||
animator.play("Run", 1);
|
||||
layerData = animator["_animatorLayersData"][1];
|
||||
childLayerCurveOwner = layerData.curveOwnerPool[childEntity.instanceId]["0.rotationQuaternion"];
|
||||
childLayerCurveOwner = layerData.curveOwnerPool[childEntity.transform.instanceId]["rotationQuaternion"];
|
||||
expect(childLayerCurveOwner.isActive).to.eq(true);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user