Skip to content

Commit

Permalink
fix particle scale mode issue
Browse files Browse the repository at this point in the history
  • Loading branch information
zxx43 committed Feb 16, 2023
1 parent df3a28f commit 8ae777e
Show file tree
Hide file tree
Showing 9 changed files with 227 additions and 69 deletions.
59 changes: 40 additions & 19 deletions cocos/particle/particle-culler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@ import type { ParticleSystem } from './particle-system';
import { Mode } from './animator/curve-range';

const _node_mat = new Mat4();
const _node_parent_inv = new Mat4();
const _node_rol = new Quat();
const _node_scale = new Vec3();
const _node_pos = new Vec3();
const _rol_mat = new Mat4();
const _scale_mat = new Mat4();
const _pos_mat = new Mat4();
const _trans_mat = new Mat4();
const _rol_scale_mat = new Mat4();

const _anim_module = [
'_colorOverLifetimeModule',
Expand Down Expand Up @@ -129,8 +134,23 @@ export class ParticleCuller {

node.invalidateChildren(TransformBit.POSITION);
if (ps.simulationSpace === Space.World) {
node.getWorldMatrix(_node_mat);
node.getWorldRotation(_node_rol);
ps.node.getWorldPosition(_node_pos);
ps.node.getWorldRotation(_node_rol);
switch (ps.scaleSpace) {
case Space.Local:
ps.node.getScale(_node_scale);
break;
case Space.World:
ps.node.getWorldScale(_node_scale);
break;
default:
break;
}
Mat4.fromTranslation(_pos_mat, _node_pos);
Mat4.fromQuat(_rol_mat, _node_rol);
Mat4.fromScaling(_scale_mat, _node_scale);
Mat4.multiply(_rol_scale_mat, _rol_mat, _scale_mat);
Mat4.multiply(_trans_mat, _pos_mat, _rol_scale_mat);
}

for (let i = 0; i < count; ++i) {
Expand All @@ -155,8 +175,8 @@ export class ParticleCuller {
Vec3.multiplyScalar(particle.velocity, particle.velocity, curveStartSpeed);

if (ps.simulationSpace === Space.World) {
Vec3.transformMat4(particle.position, particle.position, _node_mat);
Vec3.transformQuat(particle.velocity, particle.velocity, _node_rol);
Vec3.transformMat4(particle.position, particle.position, _trans_mat);
Vec3.transformMat4(particle.velocity, particle.velocity, _rol_scale_mat);
}

Vec3.copy(particle.ultimateVelocity, particle.velocity);
Expand Down Expand Up @@ -187,6 +207,8 @@ export class ParticleCuller {
const ps = this._particleSystem;
ps.node.getWorldMatrix(_node_mat);

ps.node.getWorldPosition(_node_pos);
ps.node.getWorldRotation(_node_rol);
switch (ps.scaleSpace) {
case Space.Local:
ps.node.getScale(_node_scale);
Expand All @@ -197,20 +219,22 @@ export class ParticleCuller {
default:
break;
}
Mat4.fromTranslation(_pos_mat, _node_pos);
Mat4.fromQuat(_rol_mat, _node_rol);
Mat4.fromScaling(_scale_mat, _node_scale);
Mat4.multiply(_rol_scale_mat, _rol_mat, _scale_mat);
Mat4.multiply(_trans_mat, _pos_mat, _rol_scale_mat);

this._updateList.forEach((value: IParticleModule, key: string) => {
value.update(ps.simulationSpace, _node_mat);
value.update(ps.simulationSpace, _trans_mat);
});

if (ps.simulationSpace === Space.Local) {
const r: Quat = ps.node.getRotation();
Mat4.fromQuat(this._localMat, r);
this._localMat.transpose(); // just consider rotation, use transpose as invert
}

if (ps.node.parent) {
ps.node.parent.getWorldMatrix(_node_parent_inv);
_node_parent_inv.invert();
Mat4.invert(this._localMat, _trans_mat);
this._localMat.m12 = 0;
this._localMat.m13 = 0;
this._localMat.m14 = 0;
this._localMat.m15 = 1;
}

for (let i = 0; i < particleLst.length; ++i) {
Expand All @@ -229,10 +253,7 @@ export class ParticleCuller {
this._gravity.z = 0.0;
this._gravity.w = 1.0;
if (!approx(gravityFactor, 0.0, EPSILON)) {
if (ps.node.parent) {
this._gravity = this._gravity.transformMat4(_node_parent_inv);
}
this._gravity = this._gravity.transformMat4(this._localMat);
Vec4.transformMat4(this._gravity, this._gravity, this._localMat);

p.velocity.x += this._gravity.x;
p.velocity.y += this._gravity.y;
Expand Down Expand Up @@ -271,7 +292,7 @@ export class ParticleCuller {
}
}

const worldMat = this._particleSystem.node.worldMatrix;
const worldMat = _trans_mat;
for (let i = 0; i < this._particlesAll.length; ++i) {
const p: Particle = this._particlesAll[i];
Vec3.multiply(size, _node_scale, p.size);
Expand Down
39 changes: 35 additions & 4 deletions cocos/particle/particle-system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ import { NoiseModule } from './animator/noise-module';

const _world_mat = new Mat4();
const _world_rol = new Quat();
const _trans_mat = new Mat4();
const _rol_mat = new Mat4();
const _scale_mat = new Mat4();
const _rol_scale_mat = new Mat4();

const superMaterials = Object.getOwnPropertyDescriptor(Renderer.prototype, 'sharedMaterials')!;

Expand Down Expand Up @@ -108,10 +112,24 @@ export class ParticleSystem extends ModelRenderer {
* @zh 计算粒子缩放的空间。
*/
@type(Space)
@serializable
@displayOrder(9)
@tooltip('i18n:particle_system.scaleSpace')
public scaleSpace = Space.Local;
public get scaleSpace () {
return this._scaleSpace;
}

public set scaleSpace (val) {
if (val !== this._scaleSpace) {
this._scaleSpace = val;
if (this.processor) {
this.processor.updateMaterialParams();
this.processor.updateTrailMaterial();
}
}
}

@serializable
public _scaleSpace = Space.Local;

/**
* @en Whether to modify particle size on XYZ axis.
Expand Down Expand Up @@ -1321,8 +1339,21 @@ export class ParticleSystem extends ModelRenderer {
}

if (this._simulationSpace === Space.World) {
this.node.getWorldMatrix(_world_mat);
this.node.getWorldRotation(_world_rol);
Quat.normalize(_world_rol, _world_rol);
if (this.scaleSpace === Space.World) {
this.node.getWorldMatrix(_world_mat);
Mat4.fromQuat(_rol_mat, _world_rol);
Mat4.fromScaling(_scale_mat, this.node.getWorldScale());
Mat4.multiply(_rol_scale_mat, _rol_mat, _scale_mat);
} else {
Mat4.fromScaling(_scale_mat, this.node.getScale());
Mat4.fromTranslation(_trans_mat, this.node.getWorldPosition());
Mat4.fromQuat(_rol_mat, _world_rol);
Mat4.multiply(_world_mat, _rol_mat, _scale_mat);
Mat4.multiply(_world_mat, _trans_mat, _world_mat);
Mat4.multiply(_rol_scale_mat, _rol_mat, _scale_mat);
}
}

for (let i = 0; i < count; ++i) {
Expand Down Expand Up @@ -1351,7 +1382,7 @@ export class ParticleSystem extends ModelRenderer {

if (this._simulationSpace === Space.World) {
Vec3.transformMat4(particle.position, particle.position, _world_mat);
Vec3.transformQuat(particle.velocity, particle.velocity, _world_rol);
Vec3.transformMat4(particle.velocity, particle.velocity, _rol_scale_mat);
}

Vec3.copy(particle.ultimateVelocity, particle.velocity);
Expand Down
104 changes: 82 additions & 22 deletions cocos/particle/renderer/particle-system-renderer-cpu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,11 @@ import { Pass } from '../../render-scene';
import { ParticleNoise } from '../noise';
import { NoiseModule } from '../animator/noise-module';
import { isCurveTwoValues } from '../particle-general-function';
import { Mode } from '../animator/curve-range';

const _tempAttribUV = new Vec3();
const _tempWorldTrans = new Mat4();
const _tempParentInverse = new Mat4();
const _node_rot = new Quat();
const _node_euler = new Vec3();
const _rot_mat = new Mat4();

const _anim_module = [
'_colorOverLifetimeModule',
Expand All @@ -65,6 +63,8 @@ const _uvs = [
];

const CC_USE_WORLD_SPACE = 'CC_USE_WORLD_SPACE';
const CC_USE_WORLD_SCALE = 'CC_USE_WORLD_SCALE';
const CC_USE_LINE = 'CC_USE_LINE';

const CC_RENDER_MODE = 'CC_RENDER_MODE';
const ROTATION_OVER_TIME_MODULE_ENABLE = 'ROTATION_OVER_TIME_MODULE_ENABLE';
Expand Down Expand Up @@ -143,7 +143,12 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas
private _frameTile_velLenScale: Vec4;
private _tmp_velLenScale: Vec4;
private _defaultMat: Material | null = null;
private _trailMat: Material | null = null;
private _world_rot: Quat;
private _node_scale: Vec4;
private _scale_local_trans: Mat4;
private _node_pos: Vec3;
private _pos_mat: Mat4;
private _attrs: any[];
private _particles: RecyclePool | null = null;
private _defaultTrailMat: Material | null = null;
Expand All @@ -154,6 +159,8 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas
private _uScaleHandle = 0;
private _uLenHandle = 0;
private _uNodeRotHandle = 0;
private _uTransformHandle = 0;
private _uTransTrailHandle = 0;
private _alignSpace = AlignmentSpace.View;
private _inited = false;
private _localMat: Mat4 = new Mat4();
Expand All @@ -166,17 +173,24 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas

this._frameTile_velLenScale = new Vec4(1, 1, 0, 0);
this._tmp_velLenScale = this._frameTile_velLenScale.clone();
this._world_rot = new Quat();
this._node_scale = new Vec4();
this._scale_local_trans = new Mat4();
this._node_pos = new Vec3();
this._pos_mat = new Mat4();
this._attrs = new Array(7);
this._defines = {
CC_USE_WORLD_SPACE: true,
CC_USE_WORLD_SCALE: true,
CC_USE_BILLBOARD: true,
CC_USE_STRETCHED_BILLBOARD: false,
CC_USE_HORIZONTAL_BILLBOARD: false,
CC_USE_VERTICAL_BILLBOARD: false,
};
this._trailDefines = {
CC_USE_WORLD_SPACE: true,
CC_USE_WORLD_SCALE: true,
CC_USE_LINE: false,
// CC_DRAW_WIRE_FRAME: true, // <wireframe debug>
};
}
Expand Down Expand Up @@ -335,11 +349,50 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas
switch (this._particleSystem.scaleSpace) {
case Space.Local:
this._particleSystem.node.getScale(this._node_scale);
Mat4.fromScaling(this._scale_local_trans, this._node_scale);
this._particleSystem.node.getWorldRotation(this._world_rot);
Quat.normalize(this._world_rot, this._world_rot);
Mat4.multiply(this._scale_local_trans, Mat4.fromQuat(_rot_mat, this._world_rot), this._scale_local_trans);
this._particleSystem.node.getWorldPosition(this._node_pos);
Mat4.fromTranslation(this._pos_mat, this._node_pos);
Mat4.multiply(this._scale_local_trans, this._pos_mat, this._scale_local_trans);
Mat4.copy(_tempWorldTrans, this._scale_local_trans);
pass.setUniform(this._uTransformHandle, _tempWorldTrans);
if (this._trailMat) {
this._trailMat.passes[0].setUniform(this._uTransTrailHandle, _tempWorldTrans);
}
break;
case Space.World:
this._particleSystem.node.getWorldScale(this._node_scale);
Mat4.fromScaling(this._scale_local_trans, this._node_scale);
this._particleSystem.node.getWorldRotation(this._world_rot);
Quat.normalize(this._world_rot, this._world_rot);
Mat4.multiply(this._scale_local_trans, Mat4.fromQuat(_rot_mat, this._world_rot), this._scale_local_trans);
this._particleSystem.node.getWorldPosition(this._node_pos);
Mat4.fromTranslation(this._pos_mat, this._node_pos);
Mat4.multiply(this._scale_local_trans, this._pos_mat, this._scale_local_trans);
Mat4.copy(_tempWorldTrans, this._scale_local_trans);

pass.setUniform(this._uTransformHandle, _tempWorldTrans);
if (this._trailMat) {
this._trailMat.passes[0].setUniform(this._uTransTrailHandle, _tempWorldTrans);
}
break;
default:
this._particleSystem.node.getScale(this._node_scale);
Mat4.fromScaling(this._scale_local_trans, this._node_scale);
this._particleSystem.node.getWorldRotation(this._world_rot);
Quat.normalize(this._world_rot, this._world_rot);
Mat4.multiply(this._scale_local_trans, Mat4.fromQuat(_rot_mat, this._world_rot), this._scale_local_trans);
this._particleSystem.node.getWorldPosition(this._node_pos);
Mat4.fromTranslation(this._pos_mat, this._node_pos);
Mat4.multiply(this._scale_local_trans, this._pos_mat, this._scale_local_trans);
Mat4.copy(_tempWorldTrans, this._scale_local_trans);

pass.setUniform(this._uTransformHandle, _tempWorldTrans);
if (this._trailMat) {
this._trailMat.passes[0].setUniform(this._uTransTrailHandle, _tempWorldTrans);
}
break;
}
pass.setUniform(this._uScaleHandle, this._node_scale);
Expand All @@ -352,7 +405,6 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas
if (!ps) {
return this._particles!.length;
}
ps.node.getWorldMatrix(_tempWorldTrans);
const mat: Material | null = ps.getMaterialInstance(0) || this._defaultMat;
const pass = mat!.passes[0];
this.doUpdateScale(pass);
Expand All @@ -371,15 +423,11 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas
const useGravity = !ps.gravityModifier.isZero();
if (useGravity) {
if (ps.simulationSpace === Space.Local) {
const r: Quat = ps.node.getRotation();
Mat4.fromQuat(this._localMat, r);
this._localMat.transpose(); // just consider rotation, use transpose as invert
}

if (ps.node.parent) {
const r: Quat = ps.node.parent.getWorldRotation();
Mat4.fromQuat(_tempParentInverse, r);
_tempParentInverse.transpose();
Mat4.invert(this._localMat, _tempWorldTrans);
this._localMat.m12 = 0;
this._localMat.m13 = 0;
this._localMat.m14 = 0;
this._localMat.m15 = 1;
}
}

Expand Down Expand Up @@ -408,10 +456,7 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas
this._gravity.z = 0.0;
this._gravity.w = 1.0;
if (!approx(gravityFactor, 0.0, EPSILON)) {
if (ps.node.parent) {
this._gravity = this._gravity.transformMat4(_tempParentInverse);
}
this._gravity = this._gravity.transformMat4(this._localMat);
Vec4.transformMat4(this._gravity, this._gravity, this._localMat);

p.velocity.x += this._gravity.x;
p.velocity.y += this._gravity.y;
Expand Down Expand Up @@ -661,10 +706,17 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas
this._defines[CC_USE_WORLD_SPACE] = false;
}

if (ps.scaleSpace === Space.World) {
this._defines[CC_USE_WORLD_SCALE] = true;
} else {
this._defines[CC_USE_WORLD_SCALE] = false;
}

const pass = mat.passes[0];
this._uScaleHandle = pass.getHandle('scale');
this._uLenHandle = pass.getHandle('frameTile_velLenScale');
this._uNodeRotHandle = pass.getHandle('nodeRotation');
this._uTransformHandle = pass.getHandle('worldTrans');

const renderMode = this._renderInfo!.renderMode;
const vlenScale = this._frameTile_velLenScale;
Expand Down Expand Up @@ -716,8 +768,13 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas
} else {
this._trailDefines[CC_USE_WORLD_SPACE] = false;
}
let mat = ps.getMaterialInstance(1);
if (mat === null && this._defaultTrailMat === null) {
if (ps.scaleSpace === Space.World) {
this._trailDefines[CC_USE_WORLD_SCALE] = true;
} else {
this._trailDefines[CC_USE_WORLD_SCALE] = false;
}
this._trailMat = ps.getMaterialInstance(1);
if (this._trailMat === null && this._defaultTrailMat === null) {
_matInsInfo.parent = builtinResMgr.get<Material>('default-trail-material');
_matInsInfo.owner = this._particleSystem;
_matInsInfo.subModelIdx = 1;
Expand All @@ -726,9 +783,12 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas
_matInsInfo.owner = null!;
_matInsInfo.subModelIdx = 0;
}
mat = mat || this._defaultTrailMat;
mat.recompileShaders(this._trailDefines);
trailModule.updateMaterial();
this._trailMat = this._trailMat || this._defaultTrailMat;
if (this._trailMat) {
this._uTransTrailHandle = this._trailMat.passes[0].getHandle('worldTrans');
this._trailMat.recompileShaders(this._trailDefines);
trailModule.updateMaterial();
}
}
}

Expand Down
Loading

0 comments on commit 8ae777e

Please sign in to comment.