Add Collision (Global SDF) particle module

This commit is contained in:
Wojciech Figat
2022-03-28 13:39:20 +02:00
parent bcc4a2c0a4
commit 3a9edabd03
7 changed files with 106 additions and 47 deletions

BIN
Content/Editor/Primitives/Sphere.flax (Stored with Git LFS)

Binary file not shown.

View File

@@ -1357,7 +1357,7 @@ namespace FlaxEditor.Surface.Archetypes
true, true,
(int)ModuleType.Update, (int)ModuleType.Update,
false, // Invert false, // Invert
0.0f, // Radius 5.0f, // Radius
0.0f, // Roughness 0.0f, // Roughness
0.1f, // Elasticity 0.1f, // Elasticity
0.0f, // Friction 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), 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, 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, 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), GetParticleAttribute(ModuleType.Update, 352, "Set Age", "Sets the particle age (in seconds)", typeof(float), 0.0f),

View File

@@ -1475,6 +1475,12 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode*
// Not supported // Not supported
break; break;
} }
// Collision (Global SDF)
case 336:
{
// Not supported
break;
}
#undef COLLISION_BEGIN #undef COLLISION_BEGIN
#undef COLLISION_INPUTS_FETCH #undef COLLISION_INPUTS_FETCH

View File

@@ -616,7 +616,7 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
auto position = AccessParticleAttribute(node, nodeGpu->Attributes[0], AccessMode::ReadWrite); auto position = AccessParticleAttribute(node, nodeGpu->Attributes[0], AccessMode::ReadWrite);
auto param = findOrAddGlobalSDF(); auto param = findOrAddGlobalSDF();
String wsPos = position.Value; String wsPos = position.Value;
if (((ParticleEmitterGraphGPU*)_graphStack.Peek())->SimulationSpace == ParticlesSimulationSpace::Local) if (IsLocalSimulationSpace())
wsPos = String::Format(TEXT("mul(float4({0}, 1), WorldMatrix).xyz"), wsPos); wsPos = String::Format(TEXT("mul(float4({0}, 1), WorldMatrix).xyz"), wsPos);
_includes.Add(TEXT("./Flax/GlobalSignDistanceField.hlsl")); _includes.Add(TEXT("./Flax/GlobalSignDistanceField.hlsl"));
_writer.Write( _writer.Write(
@@ -666,13 +666,8 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
case 330: case 330:
{ {
COLLISION_BEGIN(); COLLISION_BEGIN();
const Value planePosition = GetValue(node->GetBox(5), 8).AsVector3();
auto planePositionBox = node->GetBox(5); const Value planeNormal = GetValue(node->GetBox(6), 9).AsVector3();
auto planeNormalBox = node->GetBox(6);
const Value planePosition = GetValue(planePositionBox, 8).AsVector3();
const Value planeNormal = GetValue(planeNormalBox, 9).AsVector3();
_writer.Write( _writer.Write(
TEXT( TEXT(
" {{\n" " {{\n"
@@ -699,13 +694,8 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
case 331: case 331:
{ {
COLLISION_BEGIN(); COLLISION_BEGIN();
const Value spherePosition = GetValue(node->GetBox(5), 8).AsVector3();
auto spherePositionBox = node->GetBox(5); const Value sphereRadius = GetValue(node->GetBox(6), 9).AsFloat();
auto sphereRadiusBox = node->GetBox(6);
const Value spherePosition = GetValue(spherePositionBox, 8).AsVector3();
const Value sphereRadius = GetValue(sphereRadiusBox, 9).AsFloat();
_writer.Write( _writer.Write(
TEXT( TEXT(
" {{\n" " {{\n"
@@ -735,13 +725,8 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
case 332: case 332:
{ {
COLLISION_BEGIN(); COLLISION_BEGIN();
const Value boxPosition = GetValue(node->GetBox(5), 8).AsVector3();
auto boxPositionBox = node->GetBox(5); const Value boxSize = GetValue(node->GetBox(6), 9).AsVector3();
auto boxSizeBox = node->GetBox(6);
const Value boxPosition = GetValue(boxPositionBox, 8).AsVector3();
const Value boxSize = GetValue(boxSizeBox, 9).AsVector3();
_writer.Write( _writer.Write(
TEXT( TEXT(
" {{\n" " {{\n"
@@ -786,15 +771,9 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
case 333: case 333:
{ {
COLLISION_BEGIN(); COLLISION_BEGIN();
const Value cylinderPosition = GetValue(node->GetBox(5), 8).AsVector3();
auto cylinderPositionBox = node->GetBox(5); const Value cylinderHeight = GetValue(node->GetBox(6), 9).AsFloat();
auto cylinderHeightBox = node->GetBox(6); const Value cylinderRadius = GetValue(node->GetBox(7), 10).AsFloat();
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();
_writer.Write( _writer.Write(
TEXT( TEXT(
" {{\n" " {{\n"
@@ -842,13 +821,8 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
case 334: case 334:
{ {
COLLISION_BEGIN(); COLLISION_BEGIN();
const Value surfaceThickness = GetValue(node->GetBox(5), 8).AsFloat();
auto surfaceThicknessBox = node->GetBox(5);
const Value surfaceThickness = GetValue(surfaceThicknessBox, 8).AsFloat();
const auto sceneDepthTexture = findOrAddSceneTexture(MaterialSceneTextures::SceneDepth); const auto sceneDepthTexture = findOrAddSceneTexture(MaterialSceneTextures::SceneDepth);
_writer.Write( _writer.Write(
TEXT( TEXT(
" {{\n" " {{\n"
@@ -929,7 +903,51 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
" }}\n" " }}\n"
), position.Value, velocity.Value, mass.Value, param.ShaderName, attractionSpeed.Value, attractionForce.Value, stickDistance.Value, stickForce.Value); ), position.Value, velocity.Value, mass.Value, param.ShaderName, attractionSpeed.Value, attractionForce.Value, stickDistance.Value, stickForce.Value);
break; 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_BEGIN
#undef COLLISION_LOGIC #undef COLLISION_LOGIC

View File

@@ -427,14 +427,10 @@ void ParticleEmitterGPUGenerator::ProcessGroupParticles(Box* box, Node* node, Va
} }
// Particle Position (world space) // Particle Position (world space)
case 212: case 212:
{
value = AccessParticleAttribute(node, TEXT("Position"), ParticleAttribute::ValueTypes::Vector3, AccessMode::Read); 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); value = writeLocal(VariantType::Vector3, String::Format(TEXT("mul(float4({0}, 1), WorldMatrix).xyz"), value.Value), node);
}
break; break;
}
// Random Float Range // Random Float Range
case 213: case 213:
{ {

View File

@@ -156,6 +156,16 @@ private:
{ {
return box->HasConnection() ? eatBox(box->GetParent<Node>(), box->FirstConnection()) : Value::Zero; return box->HasConnection() ? eatBox(box->GetParent<Node>(), 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 #endif

View File

@@ -430,12 +430,13 @@ public:
USE_ATTRIBUTE(Position, Vector3, 0); USE_ATTRIBUTE(Position, Vector3, 0);
break; 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, 330):
case GRAPH_NODE_MAKE_TYPE(15, 331): case GRAPH_NODE_MAKE_TYPE(15, 331):
case GRAPH_NODE_MAKE_TYPE(15, 332): case GRAPH_NODE_MAKE_TYPE(15, 332):
case GRAPH_NODE_MAKE_TYPE(15, 333): case GRAPH_NODE_MAKE_TYPE(15, 333):
case GRAPH_NODE_MAKE_TYPE(15, 334): case GRAPH_NODE_MAKE_TYPE(15, 334):
case GRAPH_NODE_MAKE_TYPE(15, 336):
{ {
USE_ATTRIBUTE(Position, Vector3, 0); USE_ATTRIBUTE(Position, Vector3, 0);
USE_ATTRIBUTE(Velocity, Vector3, 1); USE_ATTRIBUTE(Velocity, Vector3, 1);