diff --git a/Source/Editor/Surface/Archetypes/ParticleModules.cs b/Source/Editor/Surface/Archetypes/ParticleModules.cs index 9dbfbce77..6ee1270ac 100644 --- a/Source/Editor/Surface/Archetypes/ParticleModules.cs +++ b/Source/Editor/Surface/Archetypes/ParticleModules.cs @@ -924,6 +924,25 @@ namespace FlaxEditor.Surface.Archetypes (int)ModuleType.Initialize, }, }, + new NodeArchetype + { + TypeID = 216, + Create = CreateParticleModuleNode, + Title = "Rotate Position Shape", + Description = "Rotate the shape.", + Flags = DefaultModuleFlags, + Size = new Float2(200, 1 * Surface.Constants.LayoutOffsetY), + DefaultValues = new object[] + { + true, + (int)ModuleType.Initialize, + Quaternion.Identity, + }, + Elements = new [] + { + NodeElementArchetype.Factory.Input(-0.5f, "Rotation", true, typeof(Quaternion), 0, 2), + } + }, GetParticleAttribute(ModuleType.Initialize, 250, "Set Position", "Sets the particle position", typeof(Float3), Float3.Zero), GetParticleAttribute(ModuleType.Initialize, 251, "Set Lifetime", "Sets the particle lifetime (in seconds)", typeof(float), 10.0f), GetParticleAttribute(ModuleType.Initialize, 252, "Set Age", "Sets the particle age (in seconds)", typeof(float), 0.0f), diff --git a/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.ParticleModules.cpp b/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.ParticleModules.cpp index 28013b5b9..4839151b4 100644 --- a/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.ParticleModules.cpp +++ b/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.ParticleModules.cpp @@ -1150,6 +1150,48 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode* // Not supported break; } + // Rotate Position Shape + case 216: + { + PARTICLE_EMITTER_MODULE("Rotate Position Shape"); + auto& positionAttr = context.Data->Buffer->Layout->Attributes[node->Attributes[0]]; + + byte* positionPtr = start + positionAttr.Offset; + + auto quatBox = node->GetBox(0); + +#define INPUTS_FETCH() \ +const Quaternion quat = (Quaternion)GetValue(quatBox, 2); +#define LOGIC() \ +Quaternion nq = Quaternion::Invert(quat); \ +Float3 v3 = *((Float3*)positionPtr); \ +Float4 v4 = Float4(v3); \ +Quaternion q = Quaternion(v4); \ +Quaternion rq = quat * (q * nq); \ +*(Float3*)positionPtr = Float3(rq.X, rq.Y, rq.Z); \ +positionPtr += stride; + + if (node->UsePerParticleDataResolve()) + { + for (int32 particleIndex = particlesStart; particleIndex < particlesEnd; particleIndex++) + { + context.ParticleIndex = particleIndex; + INPUTS_FETCH(); + LOGIC(); + } + } + else + { + INPUTS_FETCH(); + for (int32 particleIndex = particlesStart; particleIndex < particlesEnd; particleIndex++) + { + LOGIC(); + } + } +#undef INPUTS_FETCH +#undef LOGIC + break; + } // Helper macros for collision modules to share the code #define COLLISION_BEGIN() \ diff --git a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.ParticleModules.cpp b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.ParticleModules.cpp index bbf4ccdf7..160097b75 100644 --- a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.ParticleModules.cpp +++ b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.ParticleModules.cpp @@ -632,6 +632,20 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node) ), position.Value, param.ShaderName, wsPos); break; } + // Rotate position shape + case 216: + { + auto positionAttr = AccessParticleAttribute(node, nodeGpu->Attributes[0], AccessMode::Write); + const Value quaternion = tryGetValue(node->GetBox(0), Value::InitForZero(VariantType::Quaternion)).Cast(VariantType::Quaternion); + _writer.Write( + TEXT( + " {{\n" + " // Rotate position shape\n" + " {0} = QuatRotateVector({1}, {0});\n" + " }}\n" + ), positionAttr.Value, quaternion.Value); + break; + } // Helper macros for collision modules to share the code #define COLLISION_BEGIN() \