diff --git a/packages/core/src/Renderer.ts b/packages/core/src/Renderer.ts index 9b2b4f2f1..55ac568a9 100644 --- a/packages/core/src/Renderer.ts +++ b/packages/core/src/Renderer.ts @@ -68,6 +68,7 @@ export class Renderer extends Component implements IComponentCustomClone { protected _dirtyUpdateFlag: number = 0; @ignoreClone protected _rendererLayer: Vector4 = new Vector4(); + protected _transform: Transform; @deepClone private _shaderData: ShaderData = new ShaderData(ShaderDataGroup.Renderer); @@ -170,7 +171,7 @@ export class Renderer extends Component implements IComponentCustomClone { this._addResourceReferCount(this.shaderData, 1); this._onTransformChanged = this._onTransformChanged.bind(this); - this._registerEntityTransformListener(); + this._setTransform(entity.transform); shaderData.enableMacro(Renderer._receiveShadowMacro); shaderData.setVector4(Renderer._rendererLayerProperty, this._rendererLayer); @@ -364,7 +365,7 @@ export class Renderer extends Component implements IComponentCustomClone { protected override _onDestroy(): void { super._onDestroy(); - this._unRegisterEntityTransformListener(); + this._setTransform(null); this._addResourceReferCount(this.shaderData, -1); const materials = this._materials; @@ -390,7 +391,7 @@ export class Renderer extends Component implements IComponentCustomClone { * @internal */ _updateTransformShaderData(context: RenderContext, onlyMVP: boolean, batched: boolean): void { - const worldMatrix = this.entity.transform.worldMatrix; + const worldMatrix = this._transform.worldMatrix; if (onlyMVP) { this._updateProjectionRelatedShaderData(context, worldMatrix, batched); } else { @@ -440,7 +441,7 @@ export class Renderer extends Component implements IComponentCustomClone { Matrix.invert(worldMatrix, normalMatrix); normalMatrix.transpose(); - shaderData.setMatrix(Renderer._localMatrixProperty, this.entity.transform.localMatrix); + shaderData.setMatrix(Renderer._localMatrixProperty, this._transform.localMatrix); shaderData.setMatrix(Renderer._worldMatrixProperty, worldMatrix); shaderData.setMatrix(Renderer._mvMatrixProperty, mvMatrix); shaderData.setMatrix(Renderer._mvInvMatrixProperty, mvInvMatrix); @@ -463,15 +464,10 @@ export class Renderer extends Component implements IComponentCustomClone { /** * @internal */ - protected _registerEntityTransformListener(): void { - this.entity.transform._updateFlagManager.addListener(this._onTransformChanged); - } - - /** - * @internal - */ - protected _unRegisterEntityTransformListener(): void { - this.entity.transform._updateFlagManager.removeListener(this._onTransformChanged); + protected _setTransform(transform: Transform): void { + this._transform?._updateFlagManager.removeListener(this._onTransformChanged); + transform?._updateFlagManager.addListener(this._onTransformChanged); + this._transform = transform; } /** diff --git a/packages/core/src/mesh/SkinnedMeshRenderer.ts b/packages/core/src/mesh/SkinnedMeshRenderer.ts index 77b5ea931..70bdaa758 100644 --- a/packages/core/src/mesh/SkinnedMeshRenderer.ts +++ b/packages/core/src/mesh/SkinnedMeshRenderer.ts @@ -120,7 +120,7 @@ export class SkinnedMeshRenderer extends MeshRenderer { * @internal */ override _updateTransformShaderData(context: RenderContext, onlyMVP: boolean, batched: boolean): void { - const worldMatrix = (this.skin?.rootBone ?? this.entity).transform.worldMatrix; + const worldMatrix = this._transform.worldMatrix; if (onlyMVP) { this._updateProjectionRelatedShaderData(context, worldMatrix, batched); } else { @@ -219,7 +219,7 @@ export class SkinnedMeshRenderer extends MeshRenderer { protected override _updateBounds(worldBounds: BoundingBox): void { const rootBone = this.skin?.rootBone; if (rootBone) { - BoundingBox.transform(this._localBounds, rootBone.transform.worldMatrix, worldBounds); + BoundingBox.transform(this._localBounds, this._transform.worldMatrix, worldBounds); } else { super._updateBounds(worldBounds); } @@ -265,6 +265,7 @@ export class SkinnedMeshRenderer extends MeshRenderer { } break; case SkinUpdateFlag.RootBoneChanged: + this._setTransform((value).transform); this._dirtyUpdateFlag |= RendererUpdateFlags.WorldVolume; break; } diff --git a/tests/src/core/SkinnedMeshRenderer.test.ts b/tests/src/core/SkinnedMeshRenderer.test.ts index 2af09034b..219612ad9 100644 --- a/tests/src/core/SkinnedMeshRenderer.test.ts +++ b/tests/src/core/SkinnedMeshRenderer.test.ts @@ -72,8 +72,10 @@ describe("SkinnedMeshRenderer", async () => { new Matrix(1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -2, -1).invert() ]; + const position = new Vector3(); const modelMesh = new ModelMesh(engine); const entity = rootEntity.createChild("SkinEntity"); + entity.transform.position = position; const rootBone = entity.createChild("RootBone"); rootBone.createChild("Joint0"); rootBone.createChild("Joint1"); @@ -84,6 +86,8 @@ describe("SkinnedMeshRenderer", async () => { skinnedMR.skin = skin; engine.update(); + expect(skinnedMR.bounds.min).to.deep.eq(position); + expect(skinnedMR.bounds.max).to.deep.eq(position); // Test that the skin is set correctly. expect(skinnedMR.skin).to.be.equal(skin); @@ -94,6 +98,11 @@ describe("SkinnedMeshRenderer", async () => { // Test that the rootBone is set correctly. expect(skinnedMR.rootBone).to.be.equal(rootBone0); + + position.set(1, 0, 0); + rootBone0.transform.position = position; + expect(skinnedMR.bounds.min).to.deep.eq(position); + expect(skinnedMR.bounds.max).to.deep.eq(position); }); it("clone", () => {