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..42885f3c3 100644 --- a/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.ParticleModules.cpp +++ b/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.ParticleModules.cpp @@ -1150,6 +1150,47 @@ 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); \ + Quaternion q = Quaternion(v3.X, v3.Y, v3.Z, 0.0f); \ + 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..0fb687157 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 = GetValue(node->GetBox(0), 2).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() \