diff --git a/Content/Editor/Primitives/Sphere.flax b/Content/Editor/Primitives/Sphere.flax index 9ec03d998..651bc7afc 100644 --- a/Content/Editor/Primitives/Sphere.flax +++ b/Content/Editor/Primitives/Sphere.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:215797e4f6486d74eef5fcdc17bd574d4da3d32fb363e796c5ca04d9b93c6c6c -size 24621 +oid sha256:0bd78fb9c7b970d7661cff626568cd5fada5a5071740b7771241288d9bcb7995 +size 40605 diff --git a/Source/Editor/Surface/Archetypes/ParticleModules.cs b/Source/Editor/Surface/Archetypes/ParticleModules.cs index a9f4f5f5e..30f902a57 100644 --- a/Source/Editor/Surface/Archetypes/ParticleModules.cs +++ b/Source/Editor/Surface/Archetypes/ParticleModules.cs @@ -1357,7 +1357,7 @@ namespace FlaxEditor.Surface.Archetypes true, (int)ModuleType.Update, false, // Invert - 0.0f, // Radius + 5.0f, // Radius 0.0f, // Roughness 0.1f, // Elasticity 0.0f, // Friction @@ -1400,6 +1400,34 @@ namespace FlaxEditor.Surface.Archetypes NodeElementArchetype.Factory.Input(-0.5f + 3.0f, "Stick Force", true, typeof(float), 3, 5), }, }, + new NodeArchetype + { + TypeID = 336, + Create = CreateParticleModuleNode, + Title = "Collision (Global SDF)", + Description = "Collides particles with the scene Global SDF", + Flags = DefaultModuleFlags, + Size = new Vector2(200, 5 * Surface.Constants.LayoutOffsetY), + DefaultValues = new object[] + { + true, + (int)ModuleType.Update, + false, // Invert + 5.0f, // Radius + 0.4f, // Roughness + 0.1f, // Elasticity + 0.0f, // Friction + 0.0f, // Lifetime Loss + }, + Elements = new[] + { + NodeElementArchetype.Factory.Input(-0.5f + 0, "Radius", true, typeof(float), 0, 3), + NodeElementArchetype.Factory.Input(-0.5f + 1, "Roughness", true, typeof(float), 1, 4), + NodeElementArchetype.Factory.Input(-0.5f + 2, "Elasticity", true, typeof(float), 2, 5), + NodeElementArchetype.Factory.Input(-0.5f + 3, "Friction", true, typeof(float), 3, 6), + NodeElementArchetype.Factory.Input(-0.5f + 4, "Lifetime Loss", true, typeof(float), 4, 7), + }, + }, GetParticleAttribute(ModuleType.Update, 350, "Set Position", "Sets the particle position", typeof(Vector3), Vector3.Zero), GetParticleAttribute(ModuleType.Update, 351, "Set Lifetime", "Sets the particle lifetime (in seconds)", typeof(float), 10.0f), GetParticleAttribute(ModuleType.Update, 352, "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 4b6b36b55..e37378a3a 100644 --- a/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.ParticleModules.cpp +++ b/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.ParticleModules.cpp @@ -1475,6 +1475,12 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode* // Not supported break; } + // Collision (Global SDF) + case 336: + { + // Not supported + break; + } #undef COLLISION_BEGIN #undef COLLISION_INPUTS_FETCH diff --git a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.ParticleModules.cpp b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.ParticleModules.cpp index 10f3b4bd9..36a10a522 100644 --- a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.ParticleModules.cpp +++ b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.ParticleModules.cpp @@ -616,7 +616,7 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node) auto position = AccessParticleAttribute(node, nodeGpu->Attributes[0], AccessMode::ReadWrite); auto param = findOrAddGlobalSDF(); String wsPos = position.Value; - if (((ParticleEmitterGraphGPU*)_graphStack.Peek())->SimulationSpace == ParticlesSimulationSpace::Local) + if (IsLocalSimulationSpace()) wsPos = String::Format(TEXT("mul(float4({0}, 1), WorldMatrix).xyz"), wsPos); _includes.Add(TEXT("./Flax/GlobalSignDistanceField.hlsl")); _writer.Write( @@ -666,13 +666,8 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node) case 330: { COLLISION_BEGIN(); - - auto planePositionBox = node->GetBox(5); - auto planeNormalBox = node->GetBox(6); - - const Value planePosition = GetValue(planePositionBox, 8).AsVector3(); - const Value planeNormal = GetValue(planeNormalBox, 9).AsVector3(); - + const Value planePosition = GetValue(node->GetBox(5), 8).AsVector3(); + const Value planeNormal = GetValue(node->GetBox(6), 9).AsVector3(); _writer.Write( TEXT( " {{\n" @@ -699,13 +694,8 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node) case 331: { COLLISION_BEGIN(); - - auto spherePositionBox = node->GetBox(5); - auto sphereRadiusBox = node->GetBox(6); - - const Value spherePosition = GetValue(spherePositionBox, 8).AsVector3(); - const Value sphereRadius = GetValue(sphereRadiusBox, 9).AsFloat(); - + const Value spherePosition = GetValue(node->GetBox(5), 8).AsVector3(); + const Value sphereRadius = GetValue(node->GetBox(6), 9).AsFloat(); _writer.Write( TEXT( " {{\n" @@ -735,13 +725,8 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node) case 332: { COLLISION_BEGIN(); - - auto boxPositionBox = node->GetBox(5); - auto boxSizeBox = node->GetBox(6); - - const Value boxPosition = GetValue(boxPositionBox, 8).AsVector3(); - const Value boxSize = GetValue(boxSizeBox, 9).AsVector3(); - + const Value boxPosition = GetValue(node->GetBox(5), 8).AsVector3(); + const Value boxSize = GetValue(node->GetBox(6), 9).AsVector3(); _writer.Write( TEXT( " {{\n" @@ -786,15 +771,9 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node) case 333: { COLLISION_BEGIN(); - - auto cylinderPositionBox = node->GetBox(5); - auto cylinderHeightBox = node->GetBox(6); - auto cylinderRadiusBox = node->GetBox(7); - - const Value cylinderPosition = GetValue(cylinderPositionBox, 8).AsVector3(); - const Value cylinderHeight = GetValue(cylinderHeightBox, 9).AsFloat(); - const Value cylinderRadius = GetValue(cylinderRadiusBox, 10).AsFloat(); - + const Value cylinderPosition = GetValue(node->GetBox(5), 8).AsVector3(); + const Value cylinderHeight = GetValue(node->GetBox(6), 9).AsFloat(); + const Value cylinderRadius = GetValue(node->GetBox(7), 10).AsFloat(); _writer.Write( TEXT( " {{\n" @@ -842,13 +821,8 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node) case 334: { COLLISION_BEGIN(); - - auto surfaceThicknessBox = node->GetBox(5); - - const Value surfaceThickness = GetValue(surfaceThicknessBox, 8).AsFloat(); - + const Value surfaceThickness = GetValue(node->GetBox(5), 8).AsFloat(); const auto sceneDepthTexture = findOrAddSceneTexture(MaterialSceneTextures::SceneDepth); - _writer.Write( TEXT( " {{\n" @@ -929,7 +903,51 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node) " }}\n" ), position.Value, velocity.Value, mass.Value, param.ShaderName, attractionSpeed.Value, attractionForce.Value, stickDistance.Value, stickForce.Value); break; - } + } + // Collision (Global SDF) + case 336: + { + COLLISION_BEGIN(); + auto param = findOrAddGlobalSDF(); + _includes.Add(TEXT("./Flax/GlobalSignDistanceField.hlsl")); + const Char* format = IsLocalSimulationSpace() + ? TEXT( + " {{\n" + " // Collision (Global SDF)\n" + " float3 nextPos = {0} + {1} * DeltaTime;\n" + " nextPos = mul(float4(nextPos, 1), WorldMatrix).xyz;\n" + " float dist = SampleGlobalSDF({10}, {10}_Tex, nextPos);\n" + " if (dist < {5})\n" + " {{\n" + " {0} = mul(float4({0}, 1), WorldMatrix).xyz;\n" + " float3 n = normalize(SampleGlobalSDFGradient({10}, {10}_Tex, {0}, dist));\n" + " {0} += n * -dist;\n" + " {0} = mul(float4({0}, 1), InvWorldMatrix).xyz;\n" + COLLISION_LOGIC() + " }}\n" + ) + : TEXT( + " {{\n" + " // Collision (Global SDF)\n" + " float3 nextPos = {0} + {1} * DeltaTime;\n" + " float dist = SampleGlobalSDF({10}, {10}_Tex, nextPos);\n" + " if (dist < {5})\n" + " {{\n" + " float3 n = normalize(SampleGlobalSDFGradient({10}, {10}_Tex, {0}, dist));\n" + " {0} += n * -dist;\n" + COLLISION_LOGIC() + " }}\n" + ); + _writer.Write(format, + // 0-4 + positionAttr.Value, velocityAttr.Value, ageAttr.Value, invert, sign, + // 5-9 + radius.Value, roughness.Value, elasticity.Value, friction.Value, lifetimeLoss.Value, + // 10 + param.ShaderName + ); + break; + } #undef COLLISION_BEGIN #undef COLLISION_LOGIC diff --git a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Particles.cpp b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Particles.cpp index 65935f381..7b4dfefb1 100644 --- a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Particles.cpp +++ b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Particles.cpp @@ -427,14 +427,10 @@ void ParticleEmitterGPUGenerator::ProcessGroupParticles(Box* box, Node* node, Va } // Particle Position (world space) case 212: - { value = AccessParticleAttribute(node, TEXT("Position"), ParticleAttribute::ValueTypes::Vector3, AccessMode::Read); - if (((ParticleEmitterGraphGPU*)_graphStack.Peek())->SimulationSpace == ParticlesSimulationSpace::Local) - { + if (IsLocalSimulationSpace()) value = writeLocal(VariantType::Vector3, String::Format(TEXT("mul(float4({0}, 1), WorldMatrix).xyz"), value.Value), node); - } break; - } // Random Float Range case 213: { diff --git a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.h b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.h index 6e35f96af..988883965 100644 --- a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.h +++ b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.h @@ -156,6 +156,16 @@ private: { return box->HasConnection() ? eatBox(box->GetParent(), box->FirstConnection()) : Value::Zero; } + + bool IsLocalSimulationSpace() const + { + return ((ParticleEmitterGraphGPU*)_graphStack.Peek())->SimulationSpace == ParticlesSimulationSpace::Local; + } + + bool IsWorldSimulationSpace() const + { + return ((ParticleEmitterGraphGPU*)_graphStack.Peek())->SimulationSpace == ParticlesSimulationSpace::World; + } }; #endif diff --git a/Source/Engine/Particles/Graph/ParticleEmitterGraph.h b/Source/Engine/Particles/Graph/ParticleEmitterGraph.h index 566fe5b51..d03d7ebea 100644 --- a/Source/Engine/Particles/Graph/ParticleEmitterGraph.h +++ b/Source/Engine/Particles/Graph/ParticleEmitterGraph.h @@ -430,12 +430,13 @@ public: USE_ATTRIBUTE(Position, Vector3, 0); break; } - // Collision (plane/sphere/box/cylinder/depth) + // Collision (plane/sphere/box/cylinder/depth/Global SDF) case GRAPH_NODE_MAKE_TYPE(15, 330): case GRAPH_NODE_MAKE_TYPE(15, 331): case GRAPH_NODE_MAKE_TYPE(15, 332): case GRAPH_NODE_MAKE_TYPE(15, 333): case GRAPH_NODE_MAKE_TYPE(15, 334): + case GRAPH_NODE_MAKE_TYPE(15, 336): { USE_ATTRIBUTE(Position, Vector3, 0); USE_ATTRIBUTE(Velocity, Vector3, 1);