Skip to content

Commit 0ae6eab

Browse files
authored
Merge pull request #2456 from cptbtptpbcptdtptp/feat/transform
Optimize the addition and replacement logic of `Transform`
2 parents b13fd32 + 68fa63a commit 0ae6eab

12 files changed

+162
-87
lines changed

packages/core/src/Camera.ts

+7-12
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,6 @@ export class Camera extends Component {
128128
@ignoreClone
129129
private _frustumChangeFlag: BoolUpdateFlag;
130130
@ignoreClone
131-
private _transform: Transform;
132-
@ignoreClone
133131
private _isViewMatrixDirty: BoolUpdateFlag;
134132
@ignoreClone
135133
private _isInvViewProjDirty: BoolUpdateFlag;
@@ -315,7 +313,7 @@ export class Camera extends Component {
315313
this._isViewMatrixDirty.flag = false;
316314

317315
// Ignore scale
318-
const transform = this._transform;
316+
const transform = this._entity.transform;
319317
Matrix.rotationTranslation(transform.worldRotationQuaternion, transform.worldPosition, viewMatrix);
320318
viewMatrix.invert();
321319
return viewMatrix;
@@ -423,11 +421,9 @@ export class Camera extends Component {
423421
constructor(entity: Entity) {
424422
super(entity);
425423

426-
const transform = this.entity.transform;
427-
this._transform = transform;
428-
this._isViewMatrixDirty = transform.registerWorldChangeFlag();
429-
this._isInvViewProjDirty = transform.registerWorldChangeFlag();
430-
this._frustumChangeFlag = transform.registerWorldChangeFlag();
424+
this._isViewMatrixDirty = entity.registerWorldChangeFlag();
425+
this._isInvViewProjDirty = entity.registerWorldChangeFlag();
426+
this._frustumChangeFlag = entity.registerWorldChangeFlag();
431427
this._renderPipeline = new BasicRenderPipeline(this);
432428
this._addResourceReferCount(this.shaderData, 1);
433429
this._updatePixelViewport();
@@ -607,7 +603,7 @@ export class Camera extends Component {
607603
const context = engine._renderContext;
608604
const virtualCamera = this._virtualCamera;
609605

610-
const transform = this.entity.transform;
606+
const transform = this._entity.transform;
611607
Matrix.multiply(this.projectionMatrix, this.viewMatrix, virtualCamera.viewProjectionMatrix);
612608
virtualCamera.position.copyFrom(transform.worldPosition);
613609
if (virtualCamera.isOrthographic) {
@@ -738,7 +734,6 @@ export class Camera extends Component {
738734
this._virtualCamera = null;
739735
this._shaderData = null;
740736
this._frustumChangeFlag = null;
741-
this._transform = null;
742737
this._isViewMatrixDirty = null;
743738
this._isInvViewProjDirty = null;
744739
this._viewport = null;
@@ -788,7 +783,7 @@ export class Camera extends Component {
788783
private _updateShaderData(): void {
789784
const shaderData = this.shaderData;
790785

791-
const transform = this._transform;
786+
const transform = this._entity.transform;
792787
shaderData.setMatrix(Camera._inverseViewMatrixProperty, transform.worldMatrix);
793788
shaderData.setVector3(Camera._cameraPositionProperty, transform.worldPosition);
794789
shaderData.setVector3(Camera._cameraForwardProperty, transform.worldForward);
@@ -806,7 +801,7 @@ export class Camera extends Component {
806801
private _getInvViewProjMat(): Matrix {
807802
if (this._isInvViewProjDirty.flag) {
808803
this._isInvViewProjDirty.flag = false;
809-
Matrix.multiply(this._transform.worldMatrix, this._getInverseProjectionMatrix(), this._invViewProjMat);
804+
Matrix.multiply(this._entity.transform.worldMatrix, this._getInverseProjectionMatrix(), this._invViewProjMat);
810805
}
811806
return this._invViewProjMat;
812807
}

packages/core/src/ComponentsDependencies.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export class ComponentsDependencies {
4444
if (invDependencies) {
4545
for (let i = 0, len = invDependencies.length; i < len; i++) {
4646
if (entity.getComponent(invDependencies[i])) {
47-
throw `Should remove ${invDependencies[i].name} before adding ${type.name}`;
47+
throw `Should remove ${invDependencies[i].name} before remove ${type.name}`;
4848
}
4949
}
5050
}

packages/core/src/Entity.ts

+40-16
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Layer } from "./Layer";
77
import { Scene } from "./Scene";
88
import { Script } from "./Script";
99
import { Transform } from "./Transform";
10+
import { UpdateFlagManager } from "./UpdateFlagManager";
1011
import { ReferResource } from "./asset/ReferResource";
1112
import { EngineObject } from "./base";
1213
import { ComponentCloner } from "./clone/ComponentCloner";
@@ -73,8 +74,6 @@ export class Entity extends EngineObject {
7374
name: string;
7475
/** The layer the entity belongs to. */
7576
layer: Layer = Layer.Layer0;
76-
/** Transform component. */
77-
readonly transform: Transform;
7877

7978
/** @internal */
8079
_isActiveInHierarchy: boolean = false;
@@ -94,14 +93,24 @@ export class Entity extends EngineObject {
9493
_isActive: boolean = true;
9594
/** @internal */
9695
_siblingIndex: number = -1;
97-
9896
/** @internal */
9997
_isTemplate: boolean = false;
98+
/** @internal */
99+
_updateFlagManager: UpdateFlagManager = new UpdateFlagManager();
100+
/** @internal */
101+
_transform: Transform;
100102

101103
private _templateResource: ReferResource;
102104
private _parent: Entity = null;
103105
private _activeChangedComponents: Component[];
104106

107+
/**
108+
* The transform of this entity.
109+
*/
110+
get transform(): Transform {
111+
return this._transform;
112+
}
113+
105114
/**
106115
* Whether to activate locally.
107116
*/
@@ -192,12 +201,17 @@ export class Entity extends EngineObject {
192201
/**
193202
* Create a entity.
194203
* @param engine - The engine the entity belongs to
204+
* @param name - The name of the entity
205+
* @param components - The types of components you wish to add
195206
*/
196-
constructor(engine: Engine, name?: string) {
207+
constructor(engine: Engine, name?: string, ...components: ComponentConstructor[]) {
197208
super(engine);
198209
this.name = name;
199-
this.transform = this.addComponent(Transform);
200-
this._inverseWorldMatFlag = this.transform.registerWorldChangeFlag();
210+
for (let i = 0, n = components.length; i < n; i++) {
211+
this.addComponent(components[i]);
212+
}
213+
!this._transform && this.addComponent(Transform);
214+
this._inverseWorldMatFlag = this.registerWorldChangeFlag();
201215
}
202216

203217
/**
@@ -394,7 +408,10 @@ export class Entity extends EngineObject {
394408
* @returns The child entity
395409
*/
396410
createChild(name?: string): Entity {
397-
const child = new Entity(this.engine, name);
411+
const transform = this._transform;
412+
const child = transform
413+
? new Entity(this.engine, name, transform.constructor as ComponentConstructor)
414+
: new Entity(this.engine, name);
398415
child.layer = this.layer;
399416
child.parent = this;
400417
return child;
@@ -429,6 +446,14 @@ export class Entity extends EngineObject {
429446
return cloneEntity;
430447
}
431448

449+
/**
450+
* Listen for changes in the world pose of this `Entity`.
451+
* @returns Change flag
452+
*/
453+
registerWorldChangeFlag(): BoolUpdateFlag {
454+
return this._updateFlagManager.createFlag(BoolUpdateFlag);
455+
}
456+
432457
/**
433458
* @internal
434459
*/
@@ -438,8 +463,10 @@ export class Entity extends EngineObject {
438463
}
439464

440465
private _createCloneEntity(): Entity {
441-
const cloneEntity = new Entity(this._engine, this.name);
442-
466+
const transform = this._transform;
467+
const cloneEntity = transform
468+
? new Entity(this.engine, this.name, transform.constructor as ComponentConstructor)
469+
: new Entity(this.engine, this.name);
443470
const templateResource = this._templateResource;
444471
if (templateResource) {
445472
cloneEntity._templateResource = templateResource;
@@ -448,12 +475,7 @@ export class Entity extends EngineObject {
448475

449476
cloneEntity.layer = this.layer;
450477
cloneEntity._isActive = this._isActive;
451-
const { transform: cloneTransform } = cloneEntity;
452-
const { transform: srcTransform } = this;
453-
cloneTransform.position = srcTransform.position;
454-
cloneTransform.rotation = srcTransform.rotation;
455-
cloneTransform.scale = srcTransform.scale;
456-
478+
cloneEntity.transform._copyFrom(this.transform);
457479
const srcChildren = this._children;
458480
for (let i = 0, n = srcChildren.length; i < n; i++) {
459481
cloneEntity.addChild(srcChildren[i]._createCloneEntity());
@@ -478,7 +500,7 @@ export class Entity extends EngineObject {
478500
for (let i = 0, n = components.length; i < n; i++) {
479501
const sourceComp = components[i];
480502
if (!(sourceComp instanceof Transform)) {
481-
const targetComp = target.addComponent(<new (entity: Entity) => Component>sourceComp.constructor);
503+
const targetComp = target.addComponent(<ComponentConstructor>sourceComp.constructor);
482504
ComponentCloner.cloneComponent(sourceComp, targetComp, srcRoot, targetRoot, deepInstanceMap);
483505
}
484506
}
@@ -765,3 +787,5 @@ type ComponentArguments<T extends new (entity: Entity, ...args: any[]) => Compon
765787
) => Component
766788
? P
767789
: never;
790+
791+
type ComponentConstructor = new (entity: Entity) => Component;

packages/core/src/RenderPipeline/RenderQueue.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ export class RenderQueue {
186186

187187
renderState._applyStates(
188188
engine,
189-
renderer.entity.transform._isFrontFaceInvert(),
189+
renderer._transformEntity.transform._isFrontFaceInvert(),
190190
shaderPass._renderStateDataMap,
191191
material.shaderData,
192192
customStates

packages/core/src/Renderer.ts

+14-10
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ export class Renderer extends Component implements IComponentCustomClone {
5959
/** @internal */
6060
@ignoreClone
6161
_batchedTransformShaderData: boolean = false;
62+
/** @internal */
63+
@ignoreClone
64+
_transformEntity: Entity;
6265

6366
@ignoreClone
6467
protected _overrideUpdate: boolean = false;
@@ -68,8 +71,6 @@ export class Renderer extends Component implements IComponentCustomClone {
6871
protected _dirtyUpdateFlag: number = 0;
6972
@ignoreClone
7073
protected _rendererLayer: Vector4 = new Vector4();
71-
@ignoreClone
72-
protected _transform: Transform;
7374

7475
@deepClone
7576
private _shaderData: ShaderData = new ShaderData(ShaderDataGroup.Renderer);
@@ -172,7 +173,7 @@ export class Renderer extends Component implements IComponentCustomClone {
172173
this._addResourceReferCount(this.shaderData, 1);
173174

174175
this._onTransformChanged = this._onTransformChanged.bind(this);
175-
this._setTransform(entity.transform);
176+
this._setTransformEntity(entity);
176177

177178
shaderData.enableMacro(Renderer._receiveShadowMacro);
178179
shaderData.setVector4(Renderer._rendererLayerProperty, this._rendererLayer);
@@ -366,7 +367,7 @@ export class Renderer extends Component implements IComponentCustomClone {
366367
protected override _onDestroy(): void {
367368
super._onDestroy();
368369

369-
this._setTransform(null);
370+
this._setTransformEntity(null);
370371
this._addResourceReferCount(this.shaderData, -1);
371372

372373
const materials = this._materials;
@@ -392,7 +393,7 @@ export class Renderer extends Component implements IComponentCustomClone {
392393
* @internal
393394
*/
394395
_updateTransformShaderData(context: RenderContext, onlyMVP: boolean, batched: boolean): void {
395-
const worldMatrix = this._transform.worldMatrix;
396+
const worldMatrix = this._transformEntity.transform.worldMatrix;
396397
if (onlyMVP) {
397398
this._updateProjectionRelatedShaderData(context, worldMatrix, batched);
398399
} else {
@@ -442,7 +443,7 @@ export class Renderer extends Component implements IComponentCustomClone {
442443
Matrix.invert(worldMatrix, normalMatrix);
443444
normalMatrix.transpose();
444445

445-
shaderData.setMatrix(Renderer._localMatrixProperty, this._transform.localMatrix);
446+
shaderData.setMatrix(Renderer._localMatrixProperty, this._transformEntity.transform.localMatrix);
446447
shaderData.setMatrix(Renderer._worldMatrixProperty, worldMatrix);
447448
shaderData.setMatrix(Renderer._mvMatrixProperty, mvMatrix);
448449
shaderData.setMatrix(Renderer._mvInvMatrixProperty, mvInvMatrix);
@@ -465,10 +466,13 @@ export class Renderer extends Component implements IComponentCustomClone {
465466
/**
466467
* @internal
467468
*/
468-
protected _setTransform(transform: Transform): void {
469-
this._transform?._updateFlagManager.removeListener(this._onTransformChanged);
470-
transform?._updateFlagManager.addListener(this._onTransformChanged);
471-
this._transform = transform;
469+
protected _setTransformEntity(entity: Entity): void {
470+
const preEntity = this._transformEntity;
471+
if (entity !== preEntity) {
472+
preEntity?._updateFlagManager.removeListener(this._onTransformChanged);
473+
entity?._updateFlagManager.addListener(this._onTransformChanged);
474+
this._transformEntity = entity;
475+
}
472476
}
473477

474478
/**

packages/core/src/Transform.ts

+26-14
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { MathUtil, Matrix, Matrix3x3, Quaternion, Vector3 } from "@galacean/engi
22
import { BoolUpdateFlag } from "./BoolUpdateFlag";
33
import { Component } from "./Component";
44
import { Entity } from "./Entity";
5-
import { UpdateFlagManager } from "./UpdateFlagManager";
65
import { assignmentClone, deepClone, ignoreClone } from "./clone/CloneManager";
76

87
/**
@@ -56,10 +55,6 @@ export class Transform extends Component {
5655
private _parentTransformCache: Transform = null;
5756
private _dirtyFlag: number = TransformModifyFlags.WmWpWeWqWs;
5857

59-
/** @internal */
60-
@ignoreClone
61-
_updateFlagManager: UpdateFlagManager = new UpdateFlagManager();
62-
6358
/**
6459
* Local position.
6560
*/
@@ -345,6 +340,12 @@ export class Transform extends Component {
345340
this._worldRotationQuaternion._onValueChanged = this._onWorldRotationQuaternionChanged;
346341
//@ts-ignore
347342
this._scale._onValueChanged = this._onScaleChanged;
343+
344+
if (entity._transform) {
345+
throw `Entity already has a transform.`;
346+
} else {
347+
entity._transform = this;
348+
}
348349
}
349350

350351
/**
@@ -561,14 +562,6 @@ export class Transform extends Component {
561562
rotMat.getRotation(this._worldRotationQuaternion);
562563
}
563564

564-
/**
565-
* Register world transform change flag.
566-
* @returns Change flag
567-
*/
568-
registerWorldChangeFlag(): BoolUpdateFlag {
569-
return this._updateFlagManager.createFlag(BoolUpdateFlag);
570-
}
571-
572565
/**
573566
* @internal
574567
*/
@@ -588,6 +581,15 @@ export class Transform extends Component {
588581
return isInvert;
589582
}
590583

584+
/**
585+
* @internal
586+
*/
587+
_copyFrom(transform: Transform): void {
588+
this._position.copyFrom(transform._position);
589+
this._rotation.copyFrom(transform._rotation);
590+
this._scale.copyFrom(transform._scale);
591+
}
592+
591593
protected override _onDestroy(): void {
592594
super._onDestroy();
593595
//@ts-ignore
@@ -762,7 +764,7 @@ export class Transform extends Component {
762764

763765
private _worldAssociatedChange(type: number): void {
764766
this._dirtyFlag |= type;
765-
this._updateFlagManager.dispatch(type);
767+
this._entity._updateFlagManager.dispatch(type);
766768
}
767769

768770
private _rotateByQuat(rotateQuat: Quaternion, relativeToLocal: boolean): void {
@@ -875,6 +877,16 @@ export class Transform extends Component {
875877
}
876878
return this._worldUniformScaling;
877879
}
880+
881+
//--------------------------------------------------------------deprecated----------------------------------------------------------------
882+
/**
883+
* @deprecated
884+
* Listen for changes in the world pose of this `Entity`.
885+
* @returns Change flag
886+
*/
887+
registerWorldChangeFlag(): BoolUpdateFlag {
888+
return this.entity._updateFlagManager.createFlag(BoolUpdateFlag);
889+
}
878890
}
879891

880892
/**

packages/core/src/mesh/MeshRenderer.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,7 @@ export class MeshRenderer extends Renderer {
102102
const mesh = this._mesh;
103103
if (mesh) {
104104
const localBounds = mesh.bounds;
105-
const worldMatrix = this._entity.transform.worldMatrix;
106-
BoundingBox.transform(localBounds, worldMatrix, worldBounds);
105+
BoundingBox.transform(localBounds, this._transformEntity.transform.worldMatrix, worldBounds);
107106
} else {
108107
worldBounds.min.set(0, 0, 0);
109108
worldBounds.max.set(0, 0, 0);

0 commit comments

Comments
 (0)